双指针之滑动窗口

滑动窗口是双指针一个比较经典的应用,分为固定窗口变动窗口

对于变动窗口,其执行过程可以概括为:
1.初始left=0;right=0
2.向右移动right扩大窗口,寻找可行解
3.找到可行解后,向右移动left收缩窗口,优化可行解
4.循环执行第2步和第3步,直到right到达边界

变化滑动窗口:76最小覆盖子串

class Solution {
public:
//滑动窗口思想:每轮先找到可行解,然后优化可行解
    string minWindow(string s, string t) {
        //结果
        int len=s.size()+1,start=0;
        //统计t中的字符
        map<char,int>mp;
        for(auto&c:t)
            if(mp.find(c)==mp.end())
                mp[c]=1;
            else
                mp[c]++;
        //滑动窗口[left,right]
        int left=0,right=0;
        while(right<s.size()){
            char c=s[right];
            //处理当前字符
            if(mp.find(c)!=mp.end()){
                mp[c]--;
            }
            //如果当前是可行解,那么优化可行解
            while(check(mp)){
                //记录可行解
                if(right-left+1<len){
                    len=right-left+1;
                    start=left;
                }
                char c2=s[left];
                //优化可行解
                if(mp.find(c2)!=mp.end()){
                    mp[c2]++;
                }
                left++;
            }
            right++;
        }
        return len<=s.size()?s.substr(start,len):"";
    }
    
    bool check(map<char,int>&mp){
        for(auto&item:mp)
            if(item.second>0)
                return false;
        return true;
    }
};

固定滑动窗口567字符串的排列
此题利用长度为26的vector,来存放字符信息,非常巧妙。因为可以直接利用==符号,判断两个vecoter内容是否相同。
注意:本题不宜使用两个map,然后用==判断内容是否相同。因为map2[xx]=0时,仍然存留在map2中,此时如果map1中没有xx,则==结果为false。

class Solution {
public:
    //固定大小的滑动窗口
    bool checkInclusion(string s1, string s2) {
        if(s2.size()<s1.size())
            return false;
        vector<int>cs1(26,0);
        vector<int>cs2(26,0);
        int len=s1.size();
        for(int i=0;i<len;i++){
            cs1[s1[i]-'a']++;
            cs2[s2[i]-'a']++;
        }
        if(cs1==cs2)
            return true;
        for(int i=0;i+len<s2.size();i++){
            cs2[s2[i+len]-'a']++;
            cs2[s2[i]-'a']--;
            if(cs1==cs2)
                return true;
        }
        return false;
    }
};

固定滑动窗口438找到字符串中所有字母异位词

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if(s.size()<p.size())
            return {};
        vector<int>ans;
        //记录字符
        vector<int>char_s(26,0);
        vector<int>char_p(26,0);
        //初始化
        for(auto&c:p)
            char_p[c-'a']++;
        int len=p.size();
        for(int i=0;i<len;i++)
            char_s[s[i]-'a']++;
        if(char_p==char_s)
            ans.emplace_back(0);
        //滑动窗口
        for(int i=len;i<s.size();i++){
            char_s[s[i-len]-'a']--;
            char_s[s[i]-'a']++;
            if(char_s==char_p)
                ans.emplace_back(i-len+1);
        }
        return ans;
    }
};

固定滑动窗口3无重复字符的最长子串
注意:这一题的字符可以是数字、字母、符号、空格,因此vector的长度应该为ASCII表的长度,即128

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int ans=0;
        vector<int>chars(128,-1);    //记录每个字符出现的位置
        int left=0,right=0; //滑动窗口范围[left,right]
        while(right<s.size()){
            if(chars[s[right]]!=-1){
                ans=max(ans,right-left);
                while(left<chars[s[right]]+1){	//收缩左侧窗口
                    chars[s[left]]=-1;   
                    left++;
                }
            }
            chars[s[right]]=right;
            right++;
        }
        ans=max(ans,right-left);
        return ans;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值