LeetCode: 327. 区间和的个数
上篇是暴力前缀和 >> 时间复杂度
O
(
n
2
)
O(n^2)
O(n2)
博客指路: 327. 区间和的个数 (暴力前缀和)
归并排序解法 优化 >> 时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
思路:
- 分
- 核心代码
- 合 (局部排序)
归并排序
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
int len = nums.length;
if(len == 0) return 0;
long[] pre = new long[len + 1];
// 必然
pre[0] = 0;
for (int i = 1; i < pre.length; i++) {
pre[i] = pre[i - 1] + nums[i - 1];
}
int ans = divde(pre, 0, pre.length - 1, lower, upper);
return ans;
}
public int divde(long[] arr, int left, int right, int lower, int upper){
// 终止条件
if(left == right) return 0;
int mid = left + (right - left) / 2;
// 分
int n1 = divde(arr, left, mid, lower, upper);
int n2 = divde(arr, mid + 1, right, lower, upper);
int ans = n1 + n2;
// 排序处理后
// 核心代码
int cnt = left;
int i = mid + 1;
int j = mid + 1;
while(cnt <= mid){
// 找到左边界
while(i <= right && arr[i] - arr[cnt] < lower){
i++;
}
while(j <= right && arr[j] - arr[cnt] <= upper){
j++;
}
ans += j - i;
cnt++;
}
// 合
long[] sorted = new long[right - left + 1];
int a = left, b = mid + 1;
int index = 0;
while(a < mid + 1 || b <= right){
if(a > mid){
sorted[index++] = arr[b++];
}else if(b > right){
sorted[index++] = arr[a++];
}else {
//
if(arr[a] > arr[b]){
sorted[index++] = arr[b++];
}else {
// 小于等于
sorted[index++] = arr[a++];
}
}
}
// 更新原数组
for (int k = 0; k < sorted.length; k++) {
arr[left + k] = sorted[k];
}
return ans;
}
}
官方题解: 区间和的个数