【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中。

posted @ 2021-08-10 14:31  tmpUser  阅读(21)  评论(0编辑  收藏  举报