最接近零的子数组和
题目
给定一个整数数组,找到一个和最接近于零的子数组。返回第一个和最有一个指数。你的代码应该返回满足要求的子数组的起始位置和结束位置
样例
给出[-3, 1, 1, -3, 5],返回[0, 2],[1, 3], [1, 1], [2, 2] 或者 [0, 4]。
挑战
O(nlogn)的时间复杂度
题解
本题求数组中区间[i,j],使得该区间内所有元素之和最接近于0。则Sum[i,j]=Sum[0,j]-Sum[0,i-1]。为了优化时间复杂度,我们构建一个数据结构Sum保存Sum[0,j]和j的值。
对数组进行遍历,将Sum[0,j]及j依次存入一个Sum数组,再对其按sum属性大小进行排序,此时只需找到一对Sum[a],Sum[b]使得Sum[a]-Sum[b]最小,则从a,b的index属性即可得到答案。
如nums[-3, 1, 1, -3, 5],
遍历后得到Sum数组[0(0),-3(1),-2(2),-1(3),-4(4),1(5)],括号中表示index属性。
排序后得到[-4(4),-3(1),-2(2),-1(3),0(0),1(5)],
遍历可知Sum[a]-Sum[b]最小值为1,取a=1(5),b=-4(4),再从index值分析可得到答案。
public class Solution {
/**
* @param nums: A list of integers
* @return: A list of integers includes the index of the first number
* and the index of the last number
*/
class Sum
{
public int sum;
public int index;
public Sum(int sum, int index)
{
this.sum = sum;
this.index = index;
}
}
public int[] subarraySumClosest(int[] nums) {
int[] res = new int[2];
if (nums == null || nums.length == 0)
{
return res;
}
int len = nums.length;
if(len == 1)
{
res[0] = res[1] = 0;
return res;
}
Sum[] sums = new Sum[len+1];
sums[0] = new Sum(0,0);
int pre = 0;
for (int i=1;i<=len;i++)
{
sums[i] = new Sum(pre + nums[i-1],i);
pre = sums[i].sum;
}
Arrays.sort(sums, new Comparator<Sum>()
{
public int compare(Sum a, Sum b)
{
return a.sum - b.sum;
}
});
int min = Integer.MAX_VALUE;
for (int i=1;i<=len;i++)
{
if (min > sums[i].sum - sums[i-1].sum)
{
min = sums[i].sum - sums[i-1].sum;
res[0] = Math.min(sums[i].index, sums[i - 1].index);
res[1] = Math.max(sums[i].index, sums[i - 1].index) - 1;
}
}
return res;
}
}
Last Update 2016.10.17