给定一个整数数组,找到一个和最接近于零的子数组。返回第一个和最右一个指数。你的代码应该返回满足要求的子数组的起始位置和结束位置
样例
给出[-3, 1, 1, -3, 5]
,返回[0, 2]
,[1, 3]
, [1, 1]
, [2, 2]
或者 [0, 4]
。
挑战
O(nlogn)的时间复杂度
解题思路:
这道题求的是和最接近于0的子序列,暴力做法应该是N*N的时间复杂度,但是不能AC,所以在这里需要观察,所有子序列和的集合 = {0~n的子序列和,0~n的子序列和 - 0~m的子序列和},这里m<n。
所以由此我们可以知道,当(0n的子序列和)与(0m的子序列和)值非常接近的时候,则(m+1~n)即为所要求的最接近0的子序列。
当我们求到所有从0开始的子序列和,对其进行排序再遍历,我们可以得到每两个最接近的从0开始的子序列和。
最后,为了可以返回index,这里可以使用一个数据结构来一起保存sum和index。
利用sum排序,利用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
*/
public int[] subarraySumClosest(int[] nums) {
// write your code here
int[] res = new int[2];
if(nums == null || nums.length == 0)
return res;
if(nums.length == 1){
res[0] = 0;
res[0] = 0;
return res;
}
//存储前i个数(包含i)的和与i下标
Pair[] sums = new Pair[nums.length];
for(int i=0, temp=0; i<nums.length; i++){
temp += nums[i];
sums[i] = new Pair(temp, i);
}
Arrays.sort(sums, new Comparator<Pair>(){
@Override
public int compare(Pair a, Pair b){
return a.sum - b.sum;
}
});
int closest = Integer.MAX_VALUE;
for(int i=0; i<nums.length-1; i++){
if(sums[i+1].sum - sums[i].sum < closest){
closest = sums[i+1].sum - sums[i].sum;
//left = left + 1, right = right
res[0] = sums[i].index < sums[i+1].index ? sums[i].index + 1 : sums[i+1].index + 1;
res[1] = sums[i].index >= sums[i+1].index ? sums[i].index : sums[i+1].index;
}
}
return res;
}
class Pair{
public int sum;
public int index;
public Pair(int sum, int index){
this.sum = sum;
this.index = index;
}
}
}