描述
最接近零的子數組和
給定一個整數數組,找到一個和最接近於零的子數組。返回第一個和最右一個指數。你的代碼應該返回滿足要求的子數組的起始位置和結束位置
輸入:
[-3,1,1,-3,5]
輸出:
[0,2]
解釋: [0,2], [1,3], [1,1], [2,2], [0,4] 都可以
要求時間複雜度O(nlogn)
分析
暴力的想法是O(n^2)的方法來找出所有的組合,再判斷是否接近0;
進階一點的想法是利用前綴和,O(n)的過程可以求0,i的和sum[i],sum[j]-sum[i-1]就可以得到i-j之間的和,用dp也好其他方法也好,要求出所有的組合來,也是O(n^2);
進一步想。 O(nlogn)往往是二分或者排序,可以聯想到排序。(我好恨我面試的時候爲什麼沒想到這一點!!)
把所有的sum[i]及其下標一起排序,那麼相鄰的sum[i]就是接近的,只要找最接近的兩個就行,兩者的查所得的子數組和就是最接近0的。
代碼
class Solution {
public:
/*
* @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
*/
vector<int> subarraySumClosest(vector<int> &nums) {
vector<int>ans;
// write your code here
vector<pair<int,int> >sum;
int temp = 0;
sum.push_back(make_pair(temp,-1));
int len = nums.size();
for(int i = 0;i<len;i++){
temp += nums[i];
sum.push_back(make_pair(temp,i));
}
sort(sum.begin(),sum.end()); //按和排序
int diff = INT_MAX;
int start=0,end=0; //只有一個數的時候就返回0,0
for(int i = 1;i<len;i++){
if(abs(sum[i].first - sum[i-1].first)<=diff){
diff = abs(sum[i].first - sum[i-1].first);
start = min(sum[i].second, sum[i-1].second)+1; //注意這裏 是差一個的
end = max(sum[i].second,sum[i-1].second);
}
}
ans.push_back(start);
ans.push_back(end);
return ans;
}
};