0327. Count of Range Sum
https://leetcode.com/problems/count-of-range-sum
Description
Given an integer array nums
and two integers lower
and upper
, 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
inclusive, where i <= j
.
Example 1:
**Input:** nums = [-2,5,-1], lower = -2, upper = 2
**Output:** 3
**Explanation:** The three ranges are: [0,0], [2,2], and [0,2] and their respective sums are: -2, -1, 2.
Example 2:
**Input:** nums = [0], lower = 0, upper = 0
**Output:** 1
Constraints:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
-105 <= lower <= upper <= 105
The answer is guaranteed to fit in a 32-bit integer.
ac
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
// edge cases
long[] presum = new long[nums.length+1];
for (int i = 1; i < presum.length; i++) presum[i] = presum[i-1] + nums[i-1];
long[] copy = Arrays.copyOf(presum, presum.length);
Arrays.sort(copy);
long[] sortedPresum = new long[copy.length];
for (int i = 0; i < sortedPresum.length; i++) sortedPresum[i] = copy[copy.length-1-i];
int[] bit = new int[presum.length + 1];
int count = 0;
for (int i = 0; i < presum.length; i++) {
count += getSum(bit, getUpperRank(sortedPresum, (presum[i] - upper)));
count -= getSum(bit, getLowerRank(sortedPresum, presum[i] - lower)-1);
update(bit, getUpperRank(sortedPresum, presum[i]));
}
return count;
}
private void update(int[] bit, int i) {
while (i < bit.length) {
bit[i]++;
i += i & (-i);
}
}
private int getSum(int[] bit, int i) {
int res = 0;
while (i > 0) {
res += bit[i];
i -= i & (-i);
}
return res;
}
private int getUpperRank(long[] nums, long val) {
int l = 0, r = nums.length - 1;
while (l + 1 < r) {
int mid = l + (r - l) / 2;
if (nums[mid] <= val) r = mid;
else l = mid;
}
// return nums[l] >= val ? l + 1 : l;
int res = -1;
if (nums[r] > val) {
res = r;
} else if (nums[r] == val) {
res = nums[l] == val ? l : r;
} else {
if (nums[l] >= val) res = l;
else res = l - 1;
}
return res + 1;
}
private int getLowerRank(long[] nums, long val) {
int l = 0, r = nums.length - 1;
while (l + 1 < r) {
int mid = l + (r - l) / 2;
if (nums[mid] <= val) r = mid;
else l = mid;
}
int res = -1;
if (nums[l] <= val) {
res = l;
} else { // nums[l] > val
if (nums[r] <= val) {
res = r;
} else {
res = r+1;
}
}
return res + 1;
}
}
ac2: merge sort
class Solution {
int count = 0;
public int countRangeSum(int[] nums, int lower, int upper) {
// edge cases
long[] sum = new long[nums.length+1];
for (int i = 1; i < sum.length; i++) {
sum[i] = sum[i-1] + nums[i-1];
}
merge(sum, 0, sum.length - 1, lower, upper);
return count;
}
private long[] merge(long[] nums, int start, int end, int lower, int upper) {
// exit
if (start == end) return new long[]{nums[start]};
int mid = start + (end - start) / 2;
long[] left = merge(nums, start, mid, lower, upper);
long[] right = merge(nums, mid+1, end, lower, upper);
long[] res = new long[end - start + 1];
int l = 0, r = 0, i = 0;
int lo = 0, hi = 0;
while (l < left.length) {
// extract info
while (hi < right.length && right[hi] - left[l] <= upper) hi++;
while (lo < right.length && right[lo] - left[l] < lower) lo++;
count += hi - lo;
// merge
while (r < right.length && right[r] < left[l]) res[i++] = right[r++];
res[i++] = left[l++];
}
while (r < right.length) res[i++] = right[r++];
return res;
}
}
Last updated