LeetCode/solutions/209. Minimum Size Subarray Sum.md
2019-09-07 12:38:29 +08:00

57 lines
2.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [209. Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/)
# 思路
给定一个全为正数的数组和一个数字让求连续子数组之和大于等于给定值的最小子数组长度要求用O(n)和O(nlogn)两种思路。
## 思路一
先看O(n)的解法我们维护一个整数sum和两个指针left和right表示子数组的范围初始均为0然后向右移动right并累加sum直到`sum >= s`
然后尝试(需保证`sum >= s`右移左指针left此时`right - left + 1`即一个候选长度。
## 思路二
再看O(nlogn)的思路,由于给定数组全是正数,所以从左往右累加结果是递增的,即我们可以考虑二分法。
思路是,建立一个比原数组长一位的 sums 数组,其中 `sums[0]=0; sums[i] = sum(nums[0,...,i-1])`
对于每个i使得`sums[i] >= s`, 我们用二分法找到一个j使得满足`sums[j] > sums[i] - s (j < i)`即可得到候选长度`i-j+1`。
> **注意不用自己实现二分STL里lower_bound和upper_bound已经实现好了注意学习其用法。**
# C++
## 思路一
``` C++
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size();
int left = 0, right = 0, sum = 0, res = INT_MAX;
for(; right < n; right++){ // 不断向右移动right
sum += nums[right];
while(sum >= s){ // 尝试右移左指针left
res = min(res, right - left + 1);
sum -= nums[left++];
}
}
return res == INT_MAX ? 0 : res;
}
};
```
## 思路二
``` C++
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size(), res = INT_MAX;
vector<int> sums(n + 1, 0);
for (int i = 1; i <= n; i++) {
sums[i] = sums[i - 1] + nums[i - 1];
}
for (int i = n; i >= 0 && sums[i] >= s; i--) {
int j = upper_bound(sums.begin(), sums.end(), sums[i] - s) - sums.begin();
res = min(res, i - j + 1);
}
return res == INT_MAX ? 0 : res;
}
};
```