滑动窗口框架介绍
确定同向双指针 left=0, right=0
进窗口 将right指针指向的数据纳入计算范围
判断
出窗口 将left指针指向的数据从计算结果中删除
题目举例
209. 长度最小的子数组
使用滑动窗口
滑动,固定left,移动right
符合要求,更新结果
为了找到本题中最短的数组,需要移动left,找到最小长度
出窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left=0,right=0;
int n=nums.size(),sum=0,len=INT_MAX;
for(;right<n;right++){
sum+=nums[right];//进入窗口,因为right是0,让right 运行
while(target<=sum)//判断是否达到目标值
{
//如果找到目标范围就移动left以缩小范围
len=min(len,right-left+1);
sum-=nums[left++];
}
}
//len没有改变
if(len==INT_MAX){
len=0;
}
return len;
}
};
3.无重复字符的最长子串
为什么right 一直向右走不回退?回退不就把本来重复的数组重新又走了一遍更加重复了
为什么使用滑动窗口呢?连续字串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int hash[128]={0};
int left=0,right=0,n=s.size();
int ret=0;
//在第一个while循环中的都是符合要求的数组
while(right<n)
{
hash[s[right]]++;//进入窗口
while(hash[s[right]]>1)//判断
{//退出窗口
hash[s[left++]]--;
}
ret=max(ret,right-left+1);
right++;//进行下一步循环
}
return ret;
}
};
1004. 最大连续1的个数 III
转化:找出最长的子数组,0的个数不超过K个
难点:滑动窗口的判断条件
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int left=0,right=0,n=nums.size();
int ret=0;
int sum=0;
int zero=0;
while(right<n){
//判断是否==0并加入窗口
if(nums[right]==0){
zero++;
}
//判断滑动窗口是否滑动的条件:0是否达到存储max
while(zero>k){
//减少0直到最后窗口中的0的个数小于K
if(nums[left++]==0) {
zero--;
}
}
ret=max(ret,right-left+1);
right++;
}
return ret;
}
};