给定一个正整数数组 A 和一个区间. 返回和在给定区间范围内的子数组数量.
**区间i到j的和等于 sum[j+1] - sum[i]
sum[i]表示数组A中前i个元素的和
现在求start<=sum[j+1]-sum[i]<=end
可以通过遍历j 确定sum[i]的区间范围 去找j前面有多少个区间满足条件
找到大于左边界的最小元素下标和小于等于右边界的最大元素下标
为了用一个函数同时求两个下标(二分法) 可以直接求大于等于右边界+1的最小下标 即为j+1
直接与i作差就得到了区间长度 即满足条件的子数组数 加入到count中
**
public int subarraySumII(int[] A, int start, int end) {
if(A == null || A.length == 0)
return 0;
int[] sum = new int[A.length+1];
for(int i = 1; i <= A.length; i++){
sum[i] += sum[i-1] + A[i-1];
}
if(sum[1] > end || sum[A.length] < start)
return 0;
int count = 0;
for(int j = 1; j <= A.length; j++){
//A[i] -> A[j]
// start<=sum[j+1]-sum[i]<=end
int s = sum[j] - end;
int e = sum[j] - start;
count += find(sum, j, e+1) - find(sum, j, s);
}
return count;
}
private int find(int[] sum, int len, int value){
if(sum[len] < value)
return 0;
int left = 0;
int right = len;
while(left + 1 < right){
int mid = left + (right - left) / 2;
if(sum[mid] >= value){
right = mid;
}
else{
left = mid;
}
}
if(sum[left] >= value)
return left;
return right;
}
}