题目描述
给定一个整数数组 nums 。区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
请你以下标 i (0 <= i <= nums.length )为起点,元素个数逐次递增,计算子数组内的元素和。
当元素和落在范围 [lower, upper] (包含 lower 和 upper)之内时,记录子数组当前最末元素下标 j ,记作 有效 区间和 S(i, j) 。
求数组中,值位于范围 [lower, upper] (包含 lower 和 upper)之内的 有效 区间和的个数。
注意:
- 最直观的算法复杂度是 O(n2) ,请在此基础上优化你的算法。
示例:
输入:nums = [-2,5,-1], lower = -2, upper = 2,
输出:3
解释:
下标 i = 0 时,子数组 [-2]、[-2,5]、[-2,5,-1],对应元素和分别为 -2、3、2 ;其中 -2 和 2 落在范围
[lower = -2, upper = 2] 之间,因此记录有效区间和 S(0,0),S(0,2) 。 下标 i = 1 时,子数组
[5]、[5,-1] ,元素和 5、4 ;没有满足题意的有效区间和。 下标 i = 2 时,子数组 [-1] ,元素和 -1
;记录有效区间和 S(2,2) 。 故,共有 3 个有效区间和。
提示:
- 0 <= nums.length <= 10^4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-of-range-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
long[] sum = new long[nums.length+1];
for(int i = 0;i < nums.length;++i){
sum[i+1] = sum[i]+nums[i];
}
return helpCountRangeSum(sum,lower,upper,0,sum.length-1);
}
public static int helpCountRangeSum(long[] sum, int lower, int upper, int left, int right){
if(left == right){
return 0;
}else{
int mid = left + (right-left)/2;
int n1 = helpCountRangeSum(sum,lower,upper,left,mid);
int n2 = helpCountRangeSum(sum,lower,upper,mid+1,right);
int res = n1 + n2;
int index = left;
int l = mid+1;
int u = mid+1;
while(index <= mid){
while(l <= right && sum[l]-sum[index] < lower){
l++;
}
while(u <= right && sum[u]-sum[index] <= upper){
u++;
}
res += u-l;
index++;
}
long[] temNum = new long[right-left+1];
int lef = left;
int rig = mid+1;
int i = 0;
while(i < temNum.length){
if(lef > mid){
temNum[i++] = sum[rig++];
}else if(rig > right){
temNum[i++] = sum[lef++];
}else{
if(sum[lef] < sum[rig]){
temNum[i++] = sum[lef++];
}else{
temNum[i++] = sum[rig++];
}
}
}
for(int j = 0;j < temNum.length;++j){
sum[left+j] = temNum[j];
}
return res;
}
}
}