Little-Prince

导航

76. 最小覆盖子串

76. 最小覆盖子串

难度困难686给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
 
示例:
输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
 
提示:

 如果 S 中不存这样的子串,则返回空字符串 ""。
 如果 S 中存在这样的子串,我们保证它是唯一的答案。
 

 

思路:

我们可以用滑动窗口的思想解决这个问题,在滑动窗口类型的问题中都会有两个指针。一个用于「延伸」现有窗口的 r 指针,和一个用于「收缩」窗口的 l 指针。在任意时刻,只有一个指针运动,而另一个保持静止。我们在 s 上滑动窗口,通过移动 r 指针不断扩张窗口。当窗口包含 t 全部所需的字符后,如果能收缩,我们就收缩窗口直到得到最小窗口。
 
如何判断当前的窗口包含所有 ttt 所需的字符呢?我们可以用一个哈希表表示 ttt 中所有的字符以及它们的个数,用一个哈希表动态维护窗口中所有的字符以及它们的个数,如果这个动态表中包含 t 的哈希表中的所有字符,并且对应的个数都不小于 t 的哈希表中各个字符的个数,那么当前的窗口是「可行」的。
注意:这里 ttt 中可能出现重复的字符,所以我们要记录字符的个数。
 
 
只读元素:for(const auto& x:range)     
substr(start, length):返回一个从指定位置开始,并具有指定长度的子字符串。 
 
代码:
class Solution {
     unordered_map<char, int> hash_t, hash_s;

public:
    bool check()
    {
        for(const auto &p:hash_t)
        {
            if(p.second>hash_s[p.first])
                return 0;
        }
        return 1;
    }
    string minWindow(string s, string t) {
        int left = 0, right = 0, res_l = -1, len = INT_MAX;
        for(const auto &c:t)
        {
             hash_t[c]++;
             hash_s[c] = 0;
        }
           
        while(right<s.size())
        {
            if(hash_t.find(s[right])!=hash_t.end())
                hash_s[s[right]]++;
           
            while(check()&&left<=right)
            {
                if(right-left+1<len)
                {
                    len = right-left+1;
                    res_l = left;
                }
                hash_s[s[left++]]--;
            }
            right++;   

        }
        return res_l == -1 ? string() : s.substr(res_l, len);
    }
};

 

 

posted on 2020-08-09 11:17  Little-Prince  阅读(176)  评论(0编辑  收藏  举报