Time:2020/12/18LeetCode 76 最小覆盖子串 (Hard),C++刷题笔记

Time:2020/12/18
week6 滑动窗口,双指针,单调队列,单调栈

LeetCode 76 最小覆盖子串 (Hard)

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

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

提示:

  • 1 <= s.length, t.length <= 105

  • st 由英文字母组成

思路分析:

本题目中可使用双指针算法。定义双指针分别为i, j。其中i为后面的指针,j为前面的指针。ij之间的部分就是我们所截取的字符串子串,其长度为i-j+1,。可以表示为subs1=s.substring(j,i-j+1);

关键点1:如果一旦在ji之间搜索的字符子串已经满足我们的要求,那么当i指针执行**i++**继续向后移动的时候,j指针只有两种可能(原地不动,或者向后移动)。这是因为我们需要找的是满足条件的最短字符子串。

关键点2:如何判断当前子串subs1中是否已经包含t中所有的字符**?** 我们借助于数据结构hash表unordered_maphash,其keyt中所出现的字符,value为出现字符的次数。并且记录下hash的尺寸cntint cnt = hash.size();

程序解读:

step1:定义结果字符串res

step2:进入for循环,指针i往后移动。其中c的意义是当前满足条件的字符的个数。

​ 如果hash[s[i]]==1,则意味着s[i]是t中出现过的字符,且只出现过一次,此时当前满足条件的字符个数c++。

​ 如果hash[s[i]] >1,则意味着s[i]是t中出现过的字符,且不止出现过一次。

​ *step3:*执行hash[s[i]]– 。如果s[i]不是t中出现的字符,那么其对应的value将为负数。

​ *step4:*当hash[s[j]]<0 的时候,意味着当前范围的子串起点字符不是t中的元素,所以j向后移,执行j++。并且更新hash[s[j++]]++。

​ *step5:*如果c==cnt,则说明当前子串已经包含了t中所有字符,判断长度并且更新res即可。

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hash;
        for(auto c :t)
            hash[c]++;
        int cnt = hash.size();
        
        string res;
        for(int i = 0, j = 0 ,c = 0; i < s.size();i++ )
        {
            if(hash[s[i]]==1)
                c++;
            hash[s[i]]--;
            while(hash[s[j]] < 0)
                hash[s[j++]]++;
            if(c == cnt )
                if(res.empty() || res.size() >i-j+1)
                    res = s.substr(j,i-j+1);
        }
        return res;
    }
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值