题目描述:(来源于力扣209)
理解:
1)什么叫子数组,是否需要连续?
2)如果没有解怎么办?返回0?
3)如果有多个解怎么办?返回所有解,解的顺序怎么样?
1 暴力解法
使用两层遍历,只有在和满足条件时,才会更新长度length。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int length=nums.size()+1;
int sum=0;
for(int i=0;i<nums.size();++i){
sum=nums[i];
if(sum>=s)
return 1;
for(int j=i+1;j<nums.size();++j) {
sum += nums[j];
if (sum >= s){
length = min(length, j - i + 1);
break;
}
}
}
if(length>nums.size())
return 0;
return length;
}
};
2 滑动窗口
双指针法,l和r 构成一个滑动窗口。
当sum<s时,表示还需要增加元素,所以r++;
当sum>=s时,表示已经满足要求了,这时记录下此时的长度,然后l–,将窗口缩小;
【注意】:此时可能缩小窗口后,依然是sum>=s,所以还需要l–;
总结:
扩展窗口——r++;
缩小窗口——l–;
滑动窗口法:
class Solution3 {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int sum=0;
int length=nums.size()+1;
int l=0;
for(int r=0;r<nums.size();++r){
sum+=nums[r];
while (sum>=s){//缩小窗口,只要sum>=s,就还需要缩小
length=min(length,r-l+1);
sum-=nums[l++];
}
}
if(length==nums.size()+1)
return 0;
return length;
}
};
滑动窗口法:
下面这个执行效率更高一些。
class Solution2 {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int l=0,r=-1;
int sum=0;
int length=nums.size()+1;
while (l<nums.size()){
if(r+1<nums.size() && sum<s){
sum+=nums[++r];
}else{
sum-=nums[l++];
}
if(sum>=s)
length=min(length,r-l+1);
}
if(length==nums.size()+1)
return 0;
return length;
}
};