C++ 滑动窗口模板

滑动窗口模板

  • 1. 滑动窗口模板
  • 2. Leetcode对应题号题解
    • 76
    • 567
    • 438
    • 3

1. 滑动窗口模板

后面的例题全都是直接套用这个模板,熟记并理解这个模板就行了

string minWindow(string s, string t) {//寻找s中涵盖的t
        unordered_map<char, int>need, window;//初始化两个哈希表,记录窗口中的字符和需要凑齐的字符,needhe window相当于计数器,分别记录t中字符出现的次数和窗口中相应字符出现的次数
        for(char c : t) need[c]++;//map[key]访问key值,如果key不存在,C++会自动创建这个key,并把map[key]赋值为0
        int left = 0, right = 0;//窗口左开右闭,初始情况下窗口没有包含任何元素
        int valid = 0;//表示窗口中满足need条件的字符个数,如果valid=need.size(),则说明窗口已满足条件,已经完全覆盖了串T
        while(right < s.size()){
            char c = s[right];//c是将移入窗口的字符
            right++;//右移窗口
            //...进行窗口内数据的一系列更新
            printf("window:[%d,%d)\n", left, right);//debug输出位置
            while(window needs shrink){//判断左侧窗口是否要收缩
                char d = s[left];//d是将移出窗口的字符
                left++;//左移窗口
                //...进行窗口内数据的一系列更新
            }
        }
}

2. Leetcode对应题号题解

76

class Solution {
public:
    string minWindow(string s, string t) {//寻找s中涵盖的t
        //滑动窗口
        unordered_map<char, int>need, window;//初始化两个哈希表,记录窗口中的字符和需要凑齐的字符,needhe window相当于计数器,分别记录t中字符出现的次数和窗口中相应字符出现的次数
        for(char c : t) need[c]++;//map[key]访问key值,如果key不存在,C++会自动创建这个key,并把map[key]赋值为0

        int left = 0, right = 0;//窗口左开右闭,初始情况下窗口没有包含任何元素
        int valid = 0;//表示窗口中满足need条件的字符个数,如果valid=need.size(),则说明窗口已满足条件,已经完全覆盖了串T
        int start = 0, len = INT_MAX;//记录最小覆盖字串的起始索引及长度
        while(right < s.size()){
            char c = s[right];//c是将移入窗口的字符
            right++;//右移窗口
            //...进行窗口内数据的一系列更新
            if(need.count(c)){//map_name.count()的结果只能为0和1,可以以此来判断键值元素是否存在,存在则为1
                window[c]++;//窗口中相应字符出现的次数
                if(window[c] == need[c])//窗口与t串中的对应字符出现的次数相同
                    valid++;
            }
            //printf("window:[%d,%d)\n", left, right);//debug输出位置

            while(valid == need.size()){//判断左侧窗口是否要收缩
                if(right-left < len){//在这里更新最小覆盖子串
                    start = left;//索引位置
                    len = right - left;//覆盖子串的大小
                }
                char d = s[left];//d是将移出窗口的字符
                left++;//左移窗口
                //...进行窗口内数据的一系列更新
                if(need.count(d)){
                    if(window[d] == need[d])//窗口中d字符出现的次数=t串中d出现的次数
                        valid--;//value:满足need条件字符的个数,因为窗口左移了,所以value要--,方便后续更新len
                    window[d]--;//窗口中d出现的次数-1
                }
            }
        }
        return len == INT_MAX ? "" : s.substr(start, len);
        //形式 : s.substr(pos, len)
        //返回值: string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
    }
};

567

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char, int>need, window;
        for(char c : s1)    need[c]++;

        int left = 0, right = 0;
        int valid = 0;
        //窗口右+
        while(right < s2.size()){
            char c = s2[right];
            right++;
            if(need.count(c)){
                window[c]++;
                if(window[c] == need[c])
                    valid++;
            }

            //判断窗口左侧是否需要收缩
            while(right - left >= s1.size()){
                //判断是否找到了合法的子串
                if(valid == need.size())
                    return true;
                char d = s2[left];
                left++;
                //窗口内更新
                if(need.count(d)){
                    if(window[d] == need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        return false;
    }
};

438

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<char, int>need, window;
        for(char c : p) need[c]++;

        int left = 0, right = 0;
        int valid = 0;
        vector<int> res;//记录结果
        while(right < s.size()){
            char c = s[right];
            right++;
            //窗内数据更新
            if(need.count(c)){
                window[c]++;
                if(window[c] == need[c])
                    valid++;
            }
            //判断窗口左侧是否要收缩
            while(right - left >= p.size()){
                //当窗口符合条件时,把起始索引加入res
                if(valid == need.size())
                    res.push_back(left);//push_back()函数的用法:函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素
                char d = s[left];
                left++;
                //窗口内数据更新
                if(need.count(d)){
                    if(window[d] == need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        return res;
    }
};

3

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int>window;
        
        int left = 0, right = 0;
        int res;//记录结果
        while(right < s.size()){
            char c = s[right];
            right++;
            window[c]++;
            //判断窗口左侧是否需要收缩
            while(window[c] > 1){//window[1]>1说明窗口内存在重复的字符,不符合条件,窗口左侧需要收缩
                char d = s[left];
                left++;
                window[d]--;
            }
            res = max(res, right - left);
        }
        return res;
    }
};

你可能感兴趣的:(LeetCode,c++,算法,leetcode)