滑动窗口(供自己忘记时回来学习)

本文详细介绍了滑动窗口算法在不同场景下的应用,包括不固定窗口大小的最小覆盖子串问题及固定窗口大小的字符串排列问题。通过具体的代码示例展示了如何使用一个或两个哈希表来高效解决这类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.模板

1.窗口大小不固定

例题:最小覆盖子串

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

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

示例2:

输入:s = "a", t = "a"
输出:"a"

示例3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

上模板

    string minWindow(string s, string t) {
    unordered_map<char,int>need,window;
    int left=0,right=0,count=?;
    int start=?,len=?;
    for(auto c:t)
    need[c]++;
    while(right<s.size())
    {
        auto m=s[right];
        right++;//又窗口扩大
        //根据要求看是否还有其他要求
        while(满足条件)
        {
            //更新之前定义的例如len,res,start之类的数据
            auto d=s[left];//移除左边窗口的数据,缩小左边窗口
            left++;
            //进行窗口内数据的更新
        }
    }
    }
    

上代码

(1)使用两个哈希表

class Solution {
public:
    string minWindow(string s, string t) {
    unordered_map<char,int>need,window;
    int left=0,right=0,count=0;
    int start=0,len=s.size();
    for(auto c:t)
    need[c]++;
    while(right<s.size())
    {
        auto m=s[right];
        right++;
        if(need.count(m))
        {
            window[m]++;
            if(window[m]==need[m])
            count++;
        }
        while(count==need.size())
        {
            if(right-left<len)
            {
                len=right-left;
                start=left;
            }
             auto d=s[left];
             left++;
             if(need.count(d))
             {
                 if(need[d]==window[d])
                 count--;
                 window[d]--;
             }
        }
    }
    return s.substr(start,len);
    }
};

(2)使用一个哈希表

这里是另外一个博主写得代码,我自己的通不过,我是用的len=s.size()但是不能通过,上边的就没问题,应该是哪里不符合要求!

链接 :https://blog.youkuaiyun.com/qq_32523711/article/details/107584178

class Solution {
public:
    string minWindow(string s, string t) {
    unordered_map<char,int>need;
    int left=0,right=0,count=0;
    int start=0,len=INT_MAX;
    for(auto c:t)
    need[c]++;
    while(right<s.size())
    {
        auto m=s[right];
        right++;
        if(need.count(m))
        {
            need[m]--;
            if(need[m]==0)
            count++;
        }
        while(count==need.size())
        {
            if(right-left<len)
            {
                len=right-left;
                start=left;
            }
             auto d=s[left];
             left++;
             if(need.count(d))
             {
                 if(need[d]==0)
                count--;
                need[d]++;
             }
        }
    }
    return len==INT_MAX?"":s.substr(start,len);
    }
};

2.窗口大小固定

例题:字符串的排列

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

返回 true ;否则,返回 false 。

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

示例1:

输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").

示例2:

输入:s1= "ab" s2 = "eidboaoo"
输出:false

上模板


    bool checkInclusion(string s1, string s2) {
    unordered_map<char,int>need,window;
    int left=0,right=0,count=0;
    int k=s1.size();//固定窗口值
    for(auto c:s1)
    need[c]++;
    while(right<s2.size())
    {
        auto m=s2[right];//更新数据
        right++;//扩大窗口
        //看是否还有其他要求
        if(right-left==k)//用if语句
        {
        //更新数据
        auto d=s2[left];
        left++;//缩小窗口
        //是否还有更多要求
        }
    }
        return ?;
    }
};

上代码

(1)两个哈希表

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
    unordered_map<char,int>need,window;
    int left=0,right=0,count=0;
    int k=s1.size();
    for(auto c:s1)
    need[c]++;
    while(right<s2.size())
    {
        auto m=s2[right];
        right++;
        if(need.count(m))
        {
            window[m]++;
            if(need[m]==window[m])
            {
                count++;
            }
        }
        if(right-left==k)
        {
        if(count==need.size())
        return true;
        auto d=s2[left];
        left++;
        if(need.count(d))
        {
            if(need[d]==window[d])
            count--;
            window[d]--;
        }
        }
    }
        return false;
    }
};

(2)一个哈希表

同上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值