您的位置:首页 > 其它

Count of Range Sum(leetcode)

2017-10-14 12:08 218 查看

Count of Range Sum

Count of Range Sum
题目

题目解析

解决办法
sum数数

归并排序

题目

leetcode题目

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.

Example:

Given
nums
=
[-2, 5, -1]
, lower =
-2
, upper =
2
,

Return
3
.

The three ranges are :
[0, 0]
,
[2, 2]
,
[0, 2]
and their respective sums are:
-2
,
-1
,
2
.

题目解析

题目的要求就是求原数组的子数组个数,子数组满足“子数组的数之和在给定的范围
[lower, upper]
内”条件。

例子中,
nums
=
[-2, 5, -1]
,子数组为

[-2]
=>
[0, 0]


[5]
=>
[1, 1]


[-1]
=>
[2, 2]


[-2, 5]
=>
[0, 1]


[5, -1]
=>
[1, 2]


[-2, 5, -1]
=>
[0, 2]


子数组的总和在
[-2, 2]
中的子数组为
[-2]
[-1]
[-2, 5, -1]
,个数为3。

解决办法

1. sum数数

sums[i] = nums[0] + nums[1] + … + nums[i]


找到满足条件
lower <= sums[j] - sums[i] <= upper
的区间
[i, j](i <= j)
,即我们需要找到满足
sums[j] - upper <= sums[i] <= sums[j] - lower
i
的个数。

PS:函数
distance(iterator start, iterator end)
,迭代器start可以通过某种方法到达end,函数distance返回的是start到end的个数。

class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int res = 0;
long long sum = 0;
multiset<long long> sums;
sums.insert(0);
for (int i = 0; i < nums.size(); ++i) {
sum += nums[i];
res += distance(sums.lower_bound(sum - upper), sums.upper_bound(sum - lower));
sums.insert(sum);
}
return res;
}
};


2. 归并排序

将数组
sums
分为两部分:左半部left和右半部right。由于数组
sums
在构建的时候已经呈递增顺序,使得
left
right
已经排好序了。当我们遍历
left
时候,在
right
找到满足以下条件的
j, k


sums[j] - sums[i] > upper
j
是满足该不等式的第一个下标

sums[k] - sums[i] >= lower
k
是满足该不等式的第一个下标

那么在[lower, upper]之间的区间的个数是
j - k


同时我们也需要另一个下标t,用来拷贝所有满足sums[t] < sums[i]到一个寄存器Cache中以完成混合排序的过程。

class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int s = nums.size();
vector<long> sums(s + 1, 0);
for (int i = 0; i < nums.size(); ++i) {
sums[i + 1] = sums[i] + nums[i];
}
return countAndMergeSort(sums, 0, sums.size(), lower, upper);
}
int countAndMergeSort(vector<long> &sums, int start, int end, int lower, int upper) {
if (end - start <= 1) return 0;
int mid = start + (end - start) / 2;
int count = countAndMergeSort(sums, start, mid, lower, upper) + countAndMergeSort(sums, mid, end, lower, upper);
int j = mid;
int k = mid;
int t = mid;
vector<int> cache(end - start, 0);
for (int i = start, r = 0; i < mid; i++, r++) {
while (k < end && sums[k] - sums[i] < lower) k++;
while (j < end && sums[j] - sums[i] <= upper) j++;
while (t < end && sums[t] < sums[i]) cache[r++] = sums[t++];
cache[r] = sums[i];
count += j - k;
}
copy(cache.begin(), cache.begin() + t - start, sums.begin() + start);
return count;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: