前綴和應用-最接近0的子數組和

lintcode 139

描述

最接近零的子數組和
給定一個整數數組,找到一個和最接近於零的子數組。返回第一個和最右一個指數。你的代碼應該返回滿足要求的子數組的起始位置和結束位置

輸入:
[-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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章