LeetCode 76

https://leetcode.cn/problems/minimum-window-substring/description/

难度:困难

这是滑动窗口的题目。s 覆盖 t 的意思就是对 t 中的每个字母,s 里的出现次数都不小于 t 里的出现次数。出现次数使用哈希表来计数,在本题可以使用数组来进行优化。

时间复杂度:O(∣Σ∣m+n),其中 m 为 s 的长度,n 为 t 的长度,∣Σ∣ 为字符集合的大小,本题字符均为英文字母,所以 ∣Σ∣=52。注意 left 只会增加不会减少,left 每增加一次,我们就花费 O(∣Σ∣) 的时间。因为 left 至多增加 m 次,所以二重循环的时间复杂度为 O(∣Σ∣m),再算上统计 t 字母出现次数的时间 O(n),总的时间复杂度为 O(∣Σ∣m+n)。

空间复杂度:O(∣Σ∣)。如果创建了大小为 128 的数组,则 ∣Σ∣=128。

class Solution {
public:
    string minWindow(string s, string t) {
        int cnt_s[128]{}; // s 子串字母的出现次数
        int cnt_t[128]{}; // t 中字母的出现次数
        int m = s.size(), n = t.size();
        for (char c : t) {
            cnt_t[c]++;
        }
        auto check = [&]() -> bool {
            for (char c = 'a'; c <= 'z'; c++) {
                if (cnt_s[c] < cnt_t[c]) {
                    return false;
                }
            }
            for (char c = 'A'; c <= 'Z'; c++) {
                if (cnt_s[c] < cnt_t[c]) {
                    return false;
                }
            }
            return true;
        };
        int left = 0;
        int start = -1, len = INT_MAX;
        for (int right = 0; right < m; right++) {
            cnt_s[s[right]]++;
            while (check()) {
                int l = right - left + 1;
                if (l < len) {
                    len = l;
                    start = left;
                }
                cnt_s[s[left]]--;
                left++;
            }
        }
        if (len == INT_MAX) {
            return "";
        } else {
            return s.substr(start, len);
        }
    }
};