• LeetCode76. 最小覆盖子串


    滑动窗口(双指针)

    要在字符串S里找出包含字符串T的所有字符的最小子串(注意只需要包含字符串T的所有字符),不需要子串就是T。

    所以我们可以扫描一遍字符串S,找出一个满足条件包含字符串T的所有字符串子串,然后根据长度是否比之前记录的字符串长度小,更新最小子串。

    扫描字符串S需要用到滑动窗口(双指针),指针j表示子串的起始位置,子串i表示字符串的结束位置。
    由于需要计算字符的出现次数,所以考虑用哈希表。

    开两个<char, int>型哈希表hashT和hashWindow,hashT表示字符串中各个字符的出现次数,
    hashWindow表示当前子串中各个字符的出现次数。

    有了哈希表,还需要判断子串中是否包含了字符串T中的所有字符呢,这里我们引入一个变量cnt表示有效数字,
    有效数字的计算规则是:遍历子串,如果字符是字符串T中的字符且出现次数没有超过字符串T中该字符出现的次数,则cnt加一。
    因为子串中可能包含许多冗余字符。比如某字符s[i]虽然是T中的字符,
    但是在子串中的出现次数已经超过了T中该字符出现的次数(hashWindow[s[i]] > hashT[s[i]]),这时cnt是不会加一的。
    只有字符是T中字符,且在子串中出现次数小于T中出现次数时,有效数字cnt才会加一。

    有了cnt之后,只要cnt和字符串T的大小相等,就可以认为当前子串包含了字符串T中的所有字符,这时再更新一下满足题意的最小子串即可。

    代码如下:

    class Solution {
    public:
        string minWindow(string s, string t) {
            unordered_map<char, int> hashT, hashWindow;            //两个哈希表分别表示字符串t和当前子串中各个字符出现的次数
            for(auto c : t) {                              //计算t中各字符出现次数
                ++hashT[c];
            }
            string res;
            int cnt = 0;
            for(int i = 0, j = 0; i < s.size(); ++i) {      //字符串s的j ~ i部分为滑动窗口,表示当前子串
                ++hashWindow[s[i]];                         
                if(hashWindow[s[i]] <= hashT[s[i]]) {       //新增加的字符s[i]是t中字符且出现次数小于等于t中该字符出现次数,有效数字加一
                    ++cnt;
                }
                while(hashWindow[s[j]] > hashT[s[j]]) {      //由于为了新增加一个有效字符s[i],中间可能加入了很多冗余字符,因此需要判断子串的左边部分是否可以删减
                    --hashWindow[s[j]];                  //删减的条件就是,子串左边的字符出现次数已经超过了字符串t中该字符出现的次数,这时左指针可以右移,问题不大
                    ++j;
                }
                if(cnt == t.size()) {                        //有效数字等于字符串t的大小,表示当前子串包含t中的所有字符
                    if(res.empty() || res.size() > i - j + 1) {      //如果res为空(表示现在这个子串是第一个满足条件的子串)或者当前子串长度小于之前记录的子串
                        res = s.substr(j, i - j + 1);            //更新最小子串
                    }
                }
            }
            return res;
        }
    };
    
  • 相关阅读:
    设计模式
    jQuery回到顶部插件jQuery GoUp
    CentOS7+Tomcat 生产系统部署
    iOS 时间戳转换为时间
    iOS开发系列--Swift 3.0
    IOS
    iOS之宏定义#define
    #define和预编译指令
    iOS宏定义的使用与规范
    ios十进制、十六进制字符串,byte,data等之间的转换
  • 原文地址:https://www.cnblogs.com/linrj/p/13237186.html
Copyright © 2020-2023  润新知