https://leetcode-cn.com/problems/count-of-range-sum/
https://leetcode-cn.com/problems/count-of-range-sum/
套例子:
0 1 2 3
arr[ 1, -1, -2, 3] 范围[ -1, 1 ]
暴力解法:
0-0 [ 1 ] 累加和1 符合范围 √
0-1[1,-1] 累加和0 符合范围 √
0-2[1,-1,-2] 累加和-2 不符合范围 ×
0-3[1,-1,-2,3] 累加和1 符合范围 √
1-1范围的子数组
1-2范围的子数组
1-3范围的子数组
....
3-3范围的子数组
1 public static int countRangeSum2(int[] arr, int lower, int upper) { 2 //空数组或者数组中没有元素返回0 3 if (arr == null || arr.length == 0) { 4 return 0; 5 } 6 7 // 暴力美 8 int res = 0; 9 for (int i = 0; i < arr.length; i++) { // 观察数组中以i结尾的每个位置 10 for (int j = 0; j <= i; j++) { // 从0位置开始到i位置 11 int sum = 0; 12 for (int k = j; k <= i; k++) { // 随着j的变化,收集arr[j]到arr[i]的每个数 13 sum += arr[k]; 14 } 15 if (sum >= lower && sum <= upper) {// 落在给定区间上,计数器++; 16 res++; 17 } 18 } 19 } 20 return res; 21 }
这个时间复杂度O(N3)
使用前缀和可以优化到O(N2)
使用前缀和 + 归并O(N * logN)
思想解放一下:
0 1 2 3
arr[ 1, -1, -2, 3] 范围[ -1, 1 ]
preSum[1, 0, -2, 1]
第一步转化: 看子数组,必须以
0结尾 1结尾 2结尾 3结尾
0-0 1-1 2-2 3-3
0-1 1-2 2-3
0-2 1-3
0-3
a个 b个 c个 d个
第二步转化:
0 1 2 3
arr[ 1, -1, -2, 3] 范围[ -1, 1 ]
preSum[1, 0, -2, 1]
比如:有多少以3结尾的子数组累加和落在[ -1, 1 ],
前缀和有:
一个数也没有时:0
0 - 0位置的前缀和:1
0 - 1位置的前缀和:0
0 - 2位置的前缀和:-2
知道0-3累加和1,也就是问前缀和有多少落在[ -2, 0 ]上
假设0 - i整体累加和是X,题目目标[ Lower, up ],求必须以i位置结尾的子数组,有多少个在[ Lower, up ]上
等同于
去求i之前的所有前缀和中,有多少个前缀和在[ X-up, X-lower ]上。
arr[ .... ]
---->sum[ ....x ] 也就是求x前,有多少数落在[ x-up, x-lower ] 上
1 public static int merge(long[] arr, int L, int M, int R, int lower, int upper) { 2 // 不merge但是,对于右组中的每个数X,求左组中有多少个数,位于[X-upper, X-Lower] 3 int ans = 0; 4 int windowL = L; 5 int windowR = L; 6 // 目前囊括进来的数 7 // [windowL, windowR) 8 for (int i = M + 1; i <= R; i++) { 9 long min = arr[i] - upper; 10 long max = arr[i] - lower; 11 while (windowR <= M && arr[windowR] <= max) { 12 windowR++; 13 } 14 while (windowL <= M && arr[windowL] < min) { 15 windowL++; 16 } 17 ans += windowR - windowL; 18 } 19 20 // 正常merge 21 long[] help = new long[R - L + 1]; 22 int i = 0; 23 int p1 = L; 24 int p2 = M + 1; 25 while (p1 <= M && p2 <= R) { 26 help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; 27 } 28 while (p1 <= M) { 29 help[i++] = arr[p1++]; 30 } 31 while (p2 <= R) { 32 help[i++] = arr[p2++]; 33 } 34 for (i = 0; i < help.length; i++) { 35 arr[L + i] = help[i]; 36 } 37 return ans; 38 }