滑动窗总结

本文概述了滑动窗口算法在解决字符串问题中的核心逻辑,包括使用两个映射计数器来跟踪目标和窗口串的信息,以及如何通过左右指针调整窗口大小以找到满足条件的子串。通过分析LeetCode的四道题目,展示了滑动窗口在查找子串、检查包含性和寻找回文子串等场景中的应用。

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

滑动窗口的逻辑比较简单,但是细节比较复杂,其中最难的地方在于
如何判断左边窗口缩小的时机和在何处更新答案
下面对活动窗口的逻辑做一个综述;
(1),定义两个map,用作两个计数器,一个用来计算目标串的信息,另一个用来计算窗口串的信息,分别记作need和window。
(2) 定义左右指针和valid变量,用来记录窗口中符合要求的时机。当valid==need.size()的时候就要收缩左侧指针,例如leetcode第76题。
(3)逻辑在于,现在字符串中找到一个可行解,当找到这个可行解的时候就收缩左侧指针,然后比较收缩后的答案和目标答案是不是一样的,然后继续扩大右侧指针,再比较;如果满足就扩大左指针,不满足就扩大右指针,左右指针交替按照条件扩大,直到右侧指针到字符串的结尾。把leetcode上的几道题总结如下。

  1. leetcode.76
    在这里插入图片描述
class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> need,window;
        for(char c:t) need[c]++;//第一个计数器,计算目标串中有多少个目标字符;
        int left=0;
        int right=0;
        int valid=0;
        int len=INT_MAX;
        int start=0;
        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]--;
                }
                
            }
        }
        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 left=0;
        int right=0;
        int valid=0;
        for(char c:s1) need[c]++;
        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;
    }
};

3.在这里插入图片描述

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<char,int> need,window;
        vector<int> res;
        for(char c:p) need[c]++;
        int left=0;
        int 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>=p.size())
            {
                if(valid==need.size())
                {
                    res.push_back(left);
                }
                char d=s[left];
                left++;
                if(need.count(d))
                {
                    if(window[d]==need[d])
                    {
                        valid--;
                    }
                    window[d]--;
                }
            }
        } 
        return res;
    }
};

4.在这里插入图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        /*   1.官方题解
        if(s.length()==0) return 0;
        if(s.length()==1) return 1;
        unordered_set<char> lookup;//set容器装连续的不重复子串
        int left=0;
        int maxstr=0;//关键所在,记录一个最长的长度,往后滑;
        for(int i=0;i<s.length();i++)
        {
            while(lookup.find(s[i])!=lookup.end())//如果在lookup中找到了s[i]就把第一个元素
            {
                lookup.erase(s[left]);
                left++;
            }
            maxstr=max(maxstr,i-left+1);
            lookup.insert(s[i]);
        }
        return maxstr;*/
        //   2.自己的解法
       unordered_map<char,int> window;
       int left=0;
       int 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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值