力扣 76. 最小覆盖子串

0 阅读1分钟

🔗 leetcode.cn/problems/mi…

题目

  • 给定字符串 s 和 t,返回最短的 s 的子串,包含了所有 t 的字符,不存在则返回空
  • 题目保证若存在这样的子串,答案唯一

思路

  • 记录 t 的字母及频次
  • 滑动窗口 right 直到覆盖到所有的 t 字符,再收缩 left,找到符合要求子串,记录其中最短的
  • 因为 s 的子串可以包含多个 t 的字符,所以设置了 remain,即需要继续找寻的 t 的字母数,并持续记录 t 的字母及频次

代码

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hash_t;
        for (auto& ch : t) {
            hash_t[ch]++;
        }

        int l = 0;
        int remain = hash_t.size();
        string ans;
        for (int r = 0; r < s.size(); r++) {
            if (hash_t.find(s[r]) != hash_t.end()) {
                hash_t[s[r]]--;
                if (hash_t[s[r]] == 0) remain--;
            } 
            if (remain == 0) {
                while (l < s.size() && 
                    (hash_t.find(s[l]) == hash_t.end() || 
                     hash_t[s[l]] + 1 <= 0)) {
                        if (hash_t.find(s[l]) != hash_t.end()) hash_t[s[l]]++;
                        l++;
                     }
                     if (ans.empty()) ans = s.substr(l, r-l+1);
                     else if (r - l + 1 < ans.size()) ans = s.substr(l, r-l+1);
            }
        }
        return ans;
    }
};