给定一个整数数组,找到一个和最接近于零的子数组。返回第一个和最有一个指数。你的代码应该返回满足要求的子数组的起始位置和结束位置
样例
给出[-3, 1, 1, -3, 5]
,返回[0, 2]
,[1, 3]
, [1, 1]
, [2, 2]
或者[0, 4]
。
挑战
O(nlogn)的时间复杂度
********************************************
首先O(n^2)的算法很好想,直接枚举起点就行,看到挑战的复杂度,想肯定要排序或者二分什么的,这里没找出能二分的性质来,所以想只能想排序了,我们知道连续数组的和其实就是前缀和之间的差,而要求和最接近于零,也就是说,两个前缀和要最接近,那么直接前缀和排序,相邻两项比较即可
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[] a = new int[2];
int num = 0, min = Integer.MAX_VALUE;
ArrayList<Pair> list = new ArrayList<>();
list.add(new Pair(0, -1));
for(int i=0;i<nums.length;i++)
{
num += nums[i];
list.add(new Pair(num, i));
}
Collections.sort(list);
// for(int i=0;i<list.size();i++)
// System.out.println(list.get(i).a);
int start = 0, end = 0;
for(int i=1;i<list.size();i++)
{
if(Math.abs(list.get(i).a - list.get(i-1).a) <= min)
{
min = Math.abs(list.get(i).a - list.get(i-1).a);
//System.out.println(list.get(i).b+" "+list.get(i-1).b);
//System.out.println(min);
if(list.get(i).b > list.get(i-1).b)
{
start = list.get(i-1).b ;
end = list.get(i).b;
}
else
{
start = list.get(i).b ;
end = list.get(i-1).b;
}
}
}
a[0] = start;
a[1] = end;
return a;
}
}
class Pair implements Comparable<Pair>{
int a;
int b;
public Pair(int a,int b) {
// TODO Auto-generated constructor stub
this.a = a;
this.b = b;
}
@Override
public int compareTo(Pair o) {
// TODO Auto-generated method stub
if(a > o.a)
return 1;
else if(a == o.a)
return 0;
else {
return -1;
}
}
}