327. Count of Range Sum

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:
Given nums = [-2, 5, -1]lower = -2upper = 2,
Return 3.
The three ranges are : [0, 0][2, 2][0, 2] and their respective sums are: -2, -1, 2.

解题思路:此题与315的归并排序解法思想很神似,但是很难想到吧,至少对于我来说是想不到的= =。心疼自己两秒,第315题中所求即为

  • count[i] = count of nums[j] - nums[i] < 0 with j > i

而本题中经过预处理(求前缀和)之后,成为了

  • count[i] = count of a <= S[j] - S[i] <= b with j > i

可见两题思路基本一致。即在归并排序合并的过程中求出a<=S[j]-S[i]<=b,此处用j表示第一个大于等于a的位置,k表示第一个大于b的位置,则b-a即可表示这次合并的时候出现的a<=S[j]-S[i]<=b次数。

inplace_merge是stl的原地归并排序。

class Solution {
public:
    int merge(vector<long>& sum,int low,int high,int lower,int upper){
        if(high-low<=1)return 0;
        int mid=(low+high)/2;
        int res=0;
        res=merge(sum,low,mid,lower,upper)+merge(sum,mid,high,lower,upper);
        int i=low,j=mid,k=mid;
        while(i<mid){
            while(j<high&&sum[j]-sum[i]<lower)j++;
            while(k<high&&sum[k]-sum[i]<=upper)k++;
            res+=k-j;
            i++;
        }
        inplace_merge(sum.begin()+low,sum.begin()+mid,sum.begin()+high);
        return res;
    }
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        vector<long>sum(nums.size()+1,0);
        for(int i=0;i<nums.size();i++){
            sum[i+1]=sum[i]+nums[i];
        }
        return merge(sum,0,nums.size()+1,lower,upper);
    }
};

 

posted @ 2017-02-24 21:07  Tsunami_lj  阅读(160)  评论(0编辑  收藏  举报