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 = -2
, upper = 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 ofnums[j]
-nums[i]
<0
withj
>i
而本题中经过预处理(求前缀和)之后,成为了
count[i]
= count ofa
<=S[j]
-S[i]
<=b
withj
>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); } };