滑动窗口题目

滑动窗口题目模板

参考:https://labuladong.gitbook.io/algo/mu-lu-ye-1/mu-lu-ye-3/hua-dong-chuang-kou-ji-qiao-jin-jie

/* 滑动窗口算法框架 */
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++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}

题目出处:leet567

题目:

给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。

换句话说,s1 的排列之一是 s2子串

思路:构建2个map一个储存s1子串need,一个当window。右窗口滑动更新:如果右边窗口的字符在need中出现,这个need++,当某个字符数量和s1串里的数量一样时判断是否包含所有S1字符的变量valid++。左窗口收缩条件:窗口大小大于等于子串s1大小则收缩。当valid=s1.size()时表示这时找到子串位置返回true,否则收缩左窗口。

class Solution {
public:
// 判断 s 中是否存在 t 的排列
    bool checkInclusion(string t, string s) 
    {
        unordered_map<char,int>need,window;
        for(int i=0;i<t.size();i++)
            need[t[i]]++;
        int left=0,right=0;
        int valid=0;
        while(right<s.size())
        {
            char c=s[right];
            right++;
            if(need.count(c))
            {
                window[c]++;
                if(window[c]==need[c])
                    valid++;
            }
            while(right-left>=t.size())
            {
                if(valid==need.size())
                    return true;
                char d=s[left];
                left++;
                if(need.count(d))
                {
                    if(window[d]==need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        return false;
    }
};

出处:leet76

题目:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

思路:同567,左窗口收缩条件改变成当valid符合need.size()时就进行最小子串位置更新,判断当前更新子串长度是否比现在的小

class Solution {
public:
    string minWindow(string s, string t) 
    {
        int left=0,right=0;
        int valid=0,len=INT_MAX;
        int start=0;
        unordered_map<char,int>window,need;
        for(int i=0;i<t.size();i++)
        {
            need[t[i]]++;
        }
        while(right<s.size())
        {
            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;
                }
                char d=s[left];
                left++;
                if(need.count(d))
                {
                    if(window[d]==need[d])
                    {
                        valid--;
                    }
                    window[d]--;
                }
            }
        }
        if(len==INT_MAX)
            return "";
        else return s.substr(start,len);
    }
};

出处:leet3

题目:

 思路:左窗口移动条件:当窗口最右边的字符在map中大于1时左窗口左移,直到map中字符数量等于1。此时记录left和right下标,right-left作为当前更新的最长子串长度与之前最长子串取最大值。

int lengthOfLongestSubstring(string s) {
    unordered_map<char, int> window;

    int left = 0, right = 0;
    int res = 0; // 记录结果
    while (right < s.size()) {
        char c = s[right];
        right++;
        // 进行窗口内数据的一系列更新
        window[c]++;
        // 判断左侧窗口是否要收缩
        while (window[c] > 1) {
            char d = s[left];
            left++;
            // 进行窗口内数据的一系列更新
            window[d]--;
        }
        // 在这里更新答案
        res = max(res, right - left);
    }
    return res;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值