LeetCode 209 Minimum Size Subarray Sum 滑动窗口 & 二分答案
Given an array of positive integers nums
and a positive integer target
, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr]
of which the sum is greater than or equal to target
. If there is no such subarray, return 0
instead.
Solution
求最小的序列长度满足区间和 \(\ge \text{target}\).
1. \(O(n)\)
和上一道题类似,利用滑动窗口的思想。我们用 \(cur\) 记录当前的 \(sum\),如果满足 \(cur\ge target\), 就不断缩短左端点 \(l\), 然后更新答案。
点击查看代码
class Solution {
private:
int ans = INT_MAX;
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int l=0,r=0;
int cur=0;
while(r<n){
cur+=nums[r];
while(cur>=target){
ans=min(ans,r-l+1);
cur-=nums[l];l++;
}
r++;
}
return ((ans==INT_MAX)?0:ans);
}
};
2. \(O(n\log n)\)
考虑前缀和 \(sum\):
\[sum[i]=sum[i-1]+nums[i]
\]
我们从后往前遍历,然后利用 \(upper\_bound\) 来求出 \(j\) 满足:
\[sum[j]>sum[i]-s
\]
改写一下得到:
\[sum[i]-sum[j]<s
\]
除此以外,我们还有:
\[sum[i]-sum[j-1]\ge s
\]
因此 \(nums[i]\sim nums[j]\) 是区间答案。
点击查看代码
class Solution {
private:
int ans = INT_MAX;
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
vector<int> sum(n+1,0);
for(int i=0;i<n;i++){
sum[i+1] = sum[i]+nums[i];
}
// find a j : sum[j] > sum[i]-s
// ---> sum[i]-sum[j]<s && sum[i]-sum[j-1]>=s
// therefore: minimum length: i-j+1
for(int i=n;i>=1;i--){
if(sum[i]>=target){
int j = upper_bound(sum.begin(),sum.end(),sum[i]-target)-sum.begin();
ans=min(ans,i-j+1);
}
}
return ((ans==INT_MAX)?0:ans);
}
};