LeetCode 327. Count of Range Sum
对于count range sum的题目 首先应该想到的就是 树状数组和线段树就是用来高效解决此类问题的方法。
首先题意就费了一些力气去理解:
Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.
public int countRangeSum(int[] nums, int lower, int upper)
要注意 这里给的lower和upper不是index而是指的一个数值范围。 这道题目实际上问的是 在所有的subarray中sum在给定的[lower, upper]范围里的有多少。
当然 这道题目很容易用O(n^2)的方式去解。
但是题目要求不能用。
所以我们必须要像一个办法快速得到所有的sum然后check是否在规定范围中。
this problem is way too hard for me too.
and according to the solution, it can be solved in two ways:
divide and conquer, and Binary index tree(树状数组)
这是一道典型的树状数组问题 因此就只看树状数组的解法:
reference: https://leetcode.com/problems/count-of-range-sum/discuss/78006/Summary-of-the-Divide-and-Conquer-based-and-Binary-Indexed-Tree-based-solutions
public int countRangeSum(int[] nums, int lower, int upper) {
long[] sum = new long[nums.length + 1];
long[] cand = new long[3 * sum.length + 1];
int index = 0;
cand[index++] = sum[0];
cand[index++] = lower + sum[0] - 1;
cand[index++] = upper + sum[0];
for (int i = 1; i < sum.length; i++) {
sum[i] = sum[i - 1] + nums[i - 1];
cand[index++] = sum[i];
cand[index++] = lower + sum[i] - 1;
cand[index++] = upper + sum[i];
}
cand[index] = Long.MIN_VALUE; // avoid getting root of the binary indexed tree when doing binary search
Arrays.sort(cand);
int[] bit = new int[cand.length];
// build up the binary indexed tree with only elements from the prefix array "sum"
for (int i = 0; i < sum.length; i++) {
addValue(bit, Arrays.binarySearch(cand, sum[i]), 1);
}
int count = 0;
for (int i = 0; i < sum.length; i++) {
// get rid of visited elements by adding -1 to the corresponding tree nodes
addValue(bit, Arrays.binarySearch(cand, sum[i]), -1);
// add the total number of valid elements with upper bound (upper + sum[i])
count += query(bit, Arrays.binarySearch(cand, upper + sum[i]));
// minus the total number of valid elements with lower bound (lower + sum[i] - 1)
count -= query(bit, Arrays.binarySearch(cand, lower + sum[i] - 1));
}
return count;
}
private void addValue(int[] bit, int index, int value) {
while (index < bit.length) {
bit[index] += value;
index += index & -index;
}
}
private int query(int[] bit, int index) {
int sum = 0;
while (index > 0) {
sum += bit[index];
index -= index & -index;
}
return sum;
}

浙公网安备 33010602011771号