【LeetCode每日一题】[困难]327. 区间和的个数
327. 区间和的个数
算法思想:数组,并归排序思想
题目:
java代码
class Solution {
int count = 0;//区间和数量
int lower;//下限
int upper;//上限
public int countRangeSum(int[] nums, int lower, int upper) {
int n = nums.length;//数组长度
this.lower = lower;
this.upper = upper;
long[] preSum = new long[n + 1];//用来统计i之前的数组元素之和
//前序和
preSum[0] = 0;
for (int i = 0; i < n; i++) {
preSum[i+1] = preSum[i] + nums[i];
}
//递归调用统计区间和数量
countRangeMerge(preSum, 0, n);
return count;
}
private void countRangeMerge(long[] preSum, int left, int right) {
//[left,right]包括左右边界
if (left == right) {
//如果左右边界相同,表示没有元素,返回
return;
}
//划分
int mid = (left + right) / 2;//中间值
countRangeMerge(preSum, left, mid);
countRangeMerge(preSum, mid + 1, right);
//计数
int lowerIdx = mid + 1;//下限坐标
int upperIdx = mid + 1;//上限坐标
for (int i = left; i <= mid; i++) {
while (lowerIdx <= right && preSum[lowerIdx] - preSum[i] < lower) {
lowerIdx++;//向右寻找最小下限坐标
}
while (upperIdx <= right && preSum[upperIdx] - preSum[i] <= upper) {
upperIdx++;//向右寻找最大上限坐标
}
count += upperIdx - lowerIdx;//统计区间个数
}
//合并两个有序数组,使preSum在区间[left,right]有序
long[] merge = new long[right - left + 1];
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (preSum[i] <= preSum[j]) {
merge[k++] = preSum[i++];
}
else {
merge[k++] = preSum[j++];
}
}
while (i <= mid) {
merge[k++] = preSum[i++];
}
while (j <= right) {
merge[k++] = preSum[j++];
}
for (int k2 = 0; k2 < merge.length; k2++) {
preSum[left + k2] = merge[k2];
}
}
}