leedcote滑动窗口模板

1.最小覆盖子串
在这里插入图片描述
代码:

string minWindow(string s, string t) {
    unordered_map<char, int> need, window;
    for (char c : t) need[c]++;

    int left = 0, right = 0;
    int valid = 0;
    // 记录最小覆盖子串的起始索引及长度
    int start = 0, len = INT_MAX;
    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        if (need.count(c)) {
            window[c]++;
            if (window[c] == need[c])
                valid++;
        }

        // 判断左侧窗口是否要收缩
        while (valid == need.size()) {
            // 在这里更新最小覆盖子串
            if (right - left < len) {
                start = left;
                len = right - left;
            }
            // d 是将移出窗口的字符
            char d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            if (need.count(d)) {
                if (window[d] == need[d])
                    valid--;
                window[d]--;
            }                    
        }
    }
    // 返回最小覆盖子串
    return len == INT_MAX ?
        "" : s.substr(start, len);
}

2.字符串排列
在这里插入图片描述
代码中要注意的点:

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char,int> need,window;
        int right=0,left=0;
        int valid=0;
        for(auto s:s1){
            need[s]++;
        }
        while(right<s2.size()){
            char c=s2[right];
            right++;
            if(need.count(c)){
                window[c]++;
                if(window[c]==need[c])
                    valid++;
            }
            //窗口收缩的条件要具体考虑,如最小覆盖子串的收缩条件是valid == need.size(),因为他要寻找的是最小
            //子串,而当搜索条件满足时,表明当前窗口内包含了字符串T中的全部字符。且窗口内所需的字符是可以                   
            //不连续的
            //而这道题与上题不同,right-left>=s1.size()保证了当窗口大小等于s1字符串大小时,就会检测窗口内的 字
            //符是否是s1字符的排列,这样能实现检测出的满足要求的子串一定是连续的,这也和上一题形成对比,上
            //一题的满足收缩要求的窗口内需要集齐的字符不要求是连续的。
            //综上,需要集齐的字符要求是连续的,则收缩条件为right-left>=s1.size()
            while(right-left>=s1.size()){ 
                if(valid==need.size()) //一定注意是等于need.size
                    return true;
                char d=s2[left];
                left++;
                if(need.count(d)){
                    if(window[d]==need[d])
                        valid--;
                    window[d]--; 
                    //注意上面的window[c]++是跟在if(need.count(c))后面的,而这里的window[d]--一定是在最后的,
                    //因为window[c]++是先记录进入窗口的字符,再判断该字符是否已经满足了需要的数量  
                    //而window[d]--如果跟在if(need.count(d))后面,就会出现在进行 if(window[d]==need[d])判断前, 		                     	
                    //window[d]已经发生改变了,因此他是先进行 if(window[d]==need[d])判断,再进行window[d]--操作。
}
                    
            }
        }
        return false;
    }
};

3.无重复字符的最长子串
在这里插入图片描述
代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int> window;
        int right=0,left=0,maxlen=0;

        while(right<s.size()){
            char c=s[right];
            right++;
            window[c]++;
            while(window[c]>1){
                maxlen=(right-left-1)>maxlen?(right-left-1):maxlen; //刚开始最大长度错误地放在窗口缩小时更新,
                //但这样就无法准确处理长度为1的字符串了,因为此时不会满足窗口缩小的条件,也就无法更新maxlen
                char d=s[left];
                left++;
                window[d]--;
            }
            maxlen=(right-left-1)>maxlen?(right-left-1):maxlen;//因此上方的maxlen更新应该删掉,改到这里
        }
        return maxlen;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值