題目地址:Minimum Size Subarray Sum
題目簡介:
給定一個含有 n 個正整數的數組和一個正整數 s ,找出該數組中滿足其和 ≥ s 的長度最小的連續子數組。如果不存在符合條件的連續子數組,返回 0。
示例:
輸入: s = 7, nums = [2,3,1,2,4,3]
輸出: 2
解釋: 子數組 [4,3] 是該條件下的長度最小的連續子數組。
題目解析:
1、遞歸思路,但是內存錯誤(Memory Limit Exceeded):
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if len(nums) == 0:
return 0
self.size = len(nums)
ans = self.size + 1
for i in range(self.size):
ans = min (ans, 1 + self.search(s - nums[i], nums[i + 1:]))
return ans if ans <= self.size else 0
def search(self, s, nums):
if (s <= 0):
return 0
if (len(nums) == 0):
return self.size + 1
return self.search(s - nums[0], nums[1:]) + 1
2、暴力吧,計算每個小區間的總和,只要出現大於等於s,便更新最終結果。
C++:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
if (nums.empty())
return 0;
int _size = nums.size();
int ans = _size + 1;
for (int i = 0; i < _size; i++)
{
int tmp = 0;
for (int j = i; j < _size;j++)
{
tmp += nums[j];
if (tmp >= s)
{
ans = min(j - i + 1, ans);
continue;
}
}
}
return ans <= _size ? ans : 0;
}
};
3、但是需要考慮計算的複雜度,題目要求是要考慮到O(n)時間複雜度,那麼可以從全局的角度來看。
當最小區間內的數字加起來大於等於目標值後,那麼再加上額外的數字也是大於目標值。那麼反過來想,先確定一個肯定大於當前目標值的區間,逐漸縮小這個區間,並且需要滿足縮小後的區間的總和任然大於目標值。
使用雙指針,先移動右指針,找到合適的區間。然後逐漸縮小左指針,確定一個最小的區間。如此當左指針和右指針都達到最右端時,遍歷完成。時間複雜度O(2n)。
C++:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
if (nums.empty())
return 0;
int _size = nums.size();
int ans = _size + 1;
int left = 0, right = 0, sum = 0;
while (right < _size)
{
while (sum < s && right < _size)
{
sum += nums[right++];
}
while (sum >= s)
{
ans = min(ans, right - left);
sum -= nums[left++];
}
}
return ans <= _size + 1 ? 0 : ans;
}
};
Python:
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if len(nums) == 0:
return 0
_size = len(nums)
ans = _size + 1
left = 0
right = 0
total = 0
while (right < _size):
while (total < s and right < _size):
total += nums[right]
right += 1
while (total >= s):
ans = min(ans, right - left)
total -= nums[left]
left += 1
return ans if ans < _size + 1 else 0
4、二分轉載地址
C++:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
if (nums.empty())
return 0;
int n = nums.size();
int ans = n + 1;
vector<int> sums(n + 1, 0);
for (int i = 1; i < n + 1; ++i)
sums[i] = sums[i - 1] + nums[i - 1];
for (int i = 0; i < n; i++)
{
int left = i + 1, right = n, t = sums[i] + s;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (sums[mid] < t)
left = mid + 1;
else
right = mid - 1;
}
if (left == n + 1)
break;
ans = min(ans, left - i);
}
return ans == n + 1 ? 0 : ans;
}
};