算法笔记:滑动窗口 - 找到字符串中所有字母异位词

原题:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

有关双指针的思路可以参考:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

基本思路:滑动窗口(其实也是双指针的一种)

        需要的变量:

                两个指针:left、right

                两个哈希map(姑且这么叫吧):win存储窗口中已存在的,need存储窗口中必须包含的

                一个整型:done,记录win中已有多少字符的数量符合need的要求

        基本步骤:

                1. 右指针右移,扩大窗口,直到窗口符合need要求

                2. 左指针右移,缩小窗口,直到窗口不符合要求

                        此时,left、right所包含的即为符合要求的子串

                                (可能有一些+1 -1之类的边界问题,需要具体分析)

                3. 重复上述步骤,直到right越界

                注意:扩大窗口与缩小窗口的代码很大程度上是对称的

class Solution {
public:
    vector<int> findAnagrams(string src, string pat) {
    unordered_map<char, int> win, need;
    vector<int> ans;
    int left = 0, right = 0;
    int done = 0;
    for (const char& i : pat)    //初始化win与need
    {
        win[i] = 0;
        need[i]++;
    }
    int size = need.size();      //size即为done需要达到的指标
    while (right < src.size())
    {
        char in = src[right];    //待扩充的字符
        right++;                 //总之先++再说,之后再考虑窗口是否符合条件
        if (need.count(in))      //该字符在指标要求内时
        {
            win[in]++;                 //该字符进度增加
            if (win[in] == need[in])
            {
                done++;                //该字符已达成指标,done加1
            }
        }
        //printf("A %d %d %d\n", left, right, done);    //用于调试
        while (done == size)               //所有字符均达成指标,开始缩小窗口
        {
            char out = src[left];          //待删除字符
            left++;                        //和right一样,总之先++
            if (need.count(out))           //该字符在指标要求内时
            {
                win[out]--;                //该字符进度减少
                if (win[out] < need[out])
                {
                    done--;                //win中该字符数量已不足以达成指标,done减1
                }
            }
            //printf("B %d %d %d\n", left, right, done);
            if (right - left + 1 == pat.size() && done + 1 == size)
            {
                //进入该if语句时,说明上一次缩窗正好导致win无法完成指标
                ans.push_back(left - 1);   //上次缩窗前的left即为所求
            }
        }
    }
    return ans;
}
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值