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.
Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.
思路:用一个数组存储一个数列和,这些和为nums中从nums[0]开始以各项数为终点的和,这样要求的子数列和就转化为这些数列和的差的形式,枚举这些差就可以得到满足区间类的和的个数。考虑一个特殊情况,当数列和是单调递增的情况下,复杂度有所下降,因此我们使用分治中的归并排序来降低复杂度。
int range(vector<long long int>&sum, int start, int end, int upper, int lower) {
if (start >= end) {
return 0;
}
int mid = (end - start) / 2;
mid += start;
int count = range(sum, start, mid, upper, lower) + range(sum, mid + 1, end, upper, lower);
vector<long long int>record(end - start + 1, 0);
int q = mid + 1, k = q, j = q, m = 0;
for (int i = start; i <= mid; i++, m++) {
while(q <= end && sum[q] - sum[i] <= upper) {
q++;
}
while (k <= end && sum[k] - sum[i] < lower) {
k++;
}
count += q - k;
while (j <= end && sum[j] <= sum[i]) {
record[m] = sum[j];
m++;
j++;
}
record[m] = sum[i];
}
for (int i = 0; i < m; i++) {
sum[start + i] = record[i];
}
return count;
}
class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
if (nums.size() == 0) {
return 0;
}
vector<long long int>sum(nums.size() + 1, 0);
for (int i = 0; i < nums.size(); i++) {
sum[i + 1] = sum[i] + nums[i];
}
return range(sum, 0, nums.size(), upper, lower);
}
};