76. 最小覆盖子串
76. 最小覆盖子串
难度困难686给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
输出:"BANC"
提示:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
思路:
我们可以用滑动窗口的思想解决这个问题,在滑动窗口类型的问题中都会有两个指针。一个用于「延伸」现有窗口的 r 指针,和一个用于「收缩」窗口的 l 指针。在任意时刻,只有一个指针运动,而另一个保持静止。我们在 s 上滑动窗口,通过移动 r 指针不断扩张窗口。当窗口包含 t 全部所需的字符后,如果能收缩,我们就收缩窗口直到得到最小窗口。
如何判断当前的窗口包含所有 ttt 所需的字符呢?我们可以用一个哈希表表示 ttt 中所有的字符以及它们的个数,用一个哈希表动态维护窗口中所有的字符以及它们的个数,如果这个动态表中包含 t 的哈希表中的所有字符,并且对应的个数都不小于 t 的哈希表中各个字符的个数,那么当前的窗口是「可行」的。
注意:这里 ttt 中可能出现重复的字符,所以我们要记录字符的个数。
注意:这里 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) 编辑 收藏 举报