From b635aeca566f88b38eb0c7f330d72e25727061d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=A0=91=E6=A3=AE?= Date: Sat, 7 Sep 2019 12:38:29 +0800 Subject: [PATCH] Create 209. Minimum Size Subarray Sum.md --- solutions/209. Minimum Size Subarray Sum.md | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 solutions/209. Minimum Size Subarray Sum.md diff --git a/solutions/209. Minimum Size Subarray Sum.md b/solutions/209. Minimum Size Subarray Sum.md new file mode 100644 index 0000000..c04ecb9 --- /dev/null +++ b/solutions/209. Minimum Size Subarray Sum.md @@ -0,0 +1,56 @@ +# [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& 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& nums) { + int n = nums.size(), res = INT_MAX; + vector 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; + } +}; +```