滑动窗口的套路

滑动窗口是个啥

1.很显然,是个窗口,还能滑动

2.为啥要滑动?因为要在 长导轨 上匹配某个物体,并且不一定一开始就匹配上了,所以要左右滑动了

3.匹配方式有哪些?
  • 匹配物 和 窗口 完全吻合
  • 匹配物 是 窗口 的一部分,此时常常伴随着问题:什么时候窗口最小?

滑动窗口题怎么做

1.一个窗口是怎么表示的?左右边界

2.于是核心问题就变成什么时候 右边界-左边界 最小?
  • 固定左边界,右边界不断向右扩展(窗口扩大
  • 条件满足(如窗口全部包含了带匹配物),此时固定右边界,判断左边界是否可以右移(窗口是否可以缩小)
  • 得到最终的窗口大小,多组匹配结果下取最小的窗口
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    unordered_map<char, int> need, window;
    for (char c : t) need[c]++;

    int left = 0, right = 0;
    int valid = 0; 
    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        ...

        /*** debug 输出的位置 ***/
        printf("window: [%d, %d)\n", left, right);
        /********************/

        // 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}

Leetcode

76. 最小覆盖子串
别看是hard,确实是套模板就完事了

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> need, window;//模板,待匹配为need, 窗口为window
        for(auto& c : t){
            need[c]++;//模板,待匹配的都记录下来(**谁+出现几次**),方便查询
        }
        int left=0, right=0;//模板,左右边界
        int cnt = 0;//自定义,正好匹配的条件
        int start = 0;//自定义,结果对应的起始索引
        int minLen = INT_MAX;//自定义,最小字串肯定要记录最小值

        while(right < s.size()){
            char tmp = s[right];//模板
            right++;//模板
            if(need.count(tmp) != 0){
                window[tmp]++;//自定义,窗口的更新
                //窗口内的个数和
                if(window[tmp] == need[tmp]) cnt++;  //自定义,匹配完成的条件
            }
            while(cnt == need.size()){
                if(right-left < minLen){
                    minLen = right - left;
                    start = left;
                }
                char tmp1 = s[left];//模板
                left++;//模板
                //左边界右移
                if(need.count(tmp1) != 0){
                    window[tmp1]--;
                    if(window[tmp1] < need[tmp1]) cnt--;//窗口内的tmp1个数小于所需要的,肯定就不满足了,cnt--
                }
            }
        }
        if(minLen < INT_MAX){
            return s.substr(start, minLen);
        }else{
            return "";
        }
    }
};
posted @ 2020-10-09 09:58  miyanyan  阅读(107)  评论(0编辑  收藏  举报