【LeetCode-76】最小覆盖子串
问题
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例
输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"
解答
class Solution {
public:
string minWindow(string s, string t) {
int left = 0, right = 0, start = 0, minLen = INT_MAX, cnt = t.size();
unordered_map<char, int> ump;
for (char ch : t) ump[ch]++;
while (right < s.size()) {
if (ump.count(s[right]) && ump[s[right]]-- > 0) cnt--;
right++;
while (cnt == 0) {
if (ump.count(s[left]) && ump[s[left]]++ >= 0) {
if (right - left < minLen) {
minLen = right - left;
start = left;
}
cnt++;
}
left++;
}
}
return minLen == INT_MAX ? "" : s.substr(start, minLen);
}
};
重点思路
使用滑动窗口,重难点在于如何判断什么时候滑动左指针。当满足题目要求时,我们需要滑动左指针来满足题目“最短长度”这一约束,那么如何判断是否满足要求?
我们维护一个常数cnt
,用来记录离满足题目要求还差几个字母。cnt
的变化需要满足以下要求:
cnt增加:左指针滑动,删掉的字母存在于字符串
t
中;
cnt减小:右指针滑动,增加的字母存在于字符串t
中。