76. 最小覆盖子串

leetcode每日一题:76. 最小覆盖子串

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:来源:力扣(LeetCode)

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

思路:双指针,滑动窗口,右指针右移,当窗口内字符串包含T字符串,左指针收缩左移,直到滑动窗口不满足要求,记下此时满足要求最小长度字符串,然后右指针右移,循环上述步骤,右指针到头结束,找到最小长度,左指针最大下标,然后截取即可。

如何判断滑动窗口是否包含T字符串?
先对T字符串建立Hash表map_t,存储每个字符的个数,然后遍历S字符串,遇到hash表中的字符,也建立一个Hash表map_s,对应值加一。当map_s中所有字符值都大于等于map_t即满足要求,
但是滑动窗口每增加一个字符都要比较一次,费时。
此时可以使用一个变量cnt统计,用cntT的长度做比较,如果相等,肯定满足。
cnt如何加减,遍历S,当map_t中包含这个字符,且对应的值自减一仍大于等于0,cnt+1
cnt等于T字符串的长度表示满足要求,比较此时长度和最小长度。然后左指针收缩,map_t包含左指针的字符且对应值加一大于零,cnt--.
代码:

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> map;
        for(const auto &o:t)
            ++map[o];
        
        int left=0,right = 0,maxLen = s.size()+1,cnt = 0,start = 0;
        while(right<int(s.size())){
        	//当同一个字符在map中值为零,再遇到的话不会增加cnt的值
            if(--map[s[right]]>=0) cnt++;
            while(cnt==int(t.size())){
                if(right-left+1<maxLen){
                    maxLen = right-left+1;
                    start = left;
                }
                //同理
                if(++map[s[left]]>0) --cnt;
                left++;
            }
            right++;
        }

        return maxLen == s.size()+1?"":s.substr(start,maxLen);
                
    }
};

PS:针对代码中注释
例如

S=“AAAAAAAAAAB”
T=“AB”
map[A]=1,map[B]=1;
遇到s[0],--map[A]>=0,cnt++;//此时map[A]==0;
遇到s[1],--map[A]=-1<0,不会执行cnt++.
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读