您的位置:首页 > 其它

[LeetCode] Minimum Size Subarray Sum

2015-06-25 17:33 369 查看
The problem statement has stated that there are both
O(n)
and
O(nlogn)
solutions to this problem. Let's see the
O(n)
solution first (taken from this link), which is pretty clever and short.

class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int start = 0, sum = 0, minlen = INT_MAX;
for (int i = 0; i < (int)nums.size(); i++) {
sum += nums[i];
while (sum >= s) {
minlen = min(minlen, i - start + 1);
sum -= nums[start++];
}
}
return minlen == INT_MAX ? 0 : minlen;
}
};


Well, you may wonder how can it be
O(n)
since it contains an inner
while
loop. Well, the key is that the
while
loop executes at most once for each starting position
start
. Then
start
is increased by
1
and the
while
loop moves to the next element. Thus the inner
while
loop runs at most
O(n)
times during the whole
for
loop from
0
to
nums.size() - 1
. Thus both the
for
loop and
while
loop has
O(n)
time complexity in total and the overall running time is
O(n)
.

There is another
O(n)
solution in this link, which is easier to understand and prove it is
O(n)
. I have rewritten it below.

class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size();
int left = 0, right = 0, sum = 0, minlen = INT_MAX;
while (right < n) {
do sum += nums[right++];
while (right < n && sum < s);
while (left < right && sum - nums[left] >= s)
sum -= nums[left++];
if (sum >= s) minlen = min(minlen, right - left);
}
return minlen == INT_MAX ? 0 : minlen;
}
};


Now let's move on to the
O(nlogn)
solution. Well, this less efficient solution is far more difficult to come up with. The idea is to first maintain an array of accumulated summations of elements in
nums
. Specifically, for
nums = [2, 3, 1, 2, 4, 3]
in the problem statement,
sums = [0, 2, 5, 6, 8, 12, 15]
. Then for each element in
sums
, if it is not less than
s
, we search for the first element that is greater than
sums[i] - s
(in fact, this is just what the
upper_bound
function does) in
sums
using binary search.

Let's do an example. Suppose we reach
12
in
sums
, which is greater than
s = 7
. We then search for the first element in
sums
that is greater than
sums[i] - s = 12 - 7 = 5
and we find
6
. Then we know that the elements in
nums
that correspond to
6, 8, 12
sum to a number
12 - 5 = 7
which is not less than
s = 7
. Let's check for that:
6
in
sums
corresponds to
1
in
nums
,
8
in
sums
corresponds to
2
in
nums
,
12
in
sums
corresponds to
4
in
nums
.
1, 2, 4
sum to
7
, which is
12
in
sums
minus
5
in
sums
.

We add a
0
in the first position of
sums
to account for cases like
nums = [3], s = 3
.

The code is as follows.

class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
vector<int> sums = accumulate(nums);
int minlen = INT_MAX;
for (int i = 1; i <= nums.size(); i++) {
if (sums[i] >= s) {
int p = upper_bound(sums, 0, i, sums[i] - s);
if (p != -1) minlen = min(minlen, i - p + 1);
}
}
return minlen == INT_MAX ? 0 : minlen;
}
private:
vector<int> accumulate(vector<int>& nums) {
vector<int> sums(nums.size() + 1, 0);
for (int i = 1; i <= nums.size(); i++)
sums[i] = nums[i - 1] + sums[i - 1];
return sums;
}
int upper_bound(vector<int>& sums, int left, int right, int target) {
int l = left, r = right;
while (l < r) {
int m = l + ((r - l) >> 1);
if (sums[m] <= target) l = m + 1;
else r = m;
}
if (sums[r] > target) return r;
if (sums[l] > target) return l;
return -1;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: