76. 最小覆盖子串

492 阅读1分钟

学习剖析一次: 76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC"

leetcode-cn.com/problems/mi…

11111.gif


class Solution {
    public:
        unordered_map <char, int> wordCountMap, lrmap;

        bool isContainAll() {
            for(const auto &p: wordCountMap) {
                if(lrmap[p.first] < p.second) {
                    return false;
                }
            }
            return true;
        };
        string minWindow(string s, string t) {
            for(const auto &c: t) {
                ++wordCountMap[c];
            }
            int l = 0, r = -1;
            // 俩个字段记录:子串长度和起始位置
            int minLen = INT_MAX,  minLenLeft = -1
       
            // l...r 
            while (r < int(s.size()))
            {
                // 当前字符在Word中,记录总出现次数
                // r右指针向前+1
                if (wordCountMap.find(s[++r]) != wordCountMap.end())
                {
                    ++lrmap[s[r]];
                }
                // 当lrmap中字符出现次数符合Word
                // 判断l-r范围内的字符是否包含所有Word字符
                while(isContainAll() && l <= r) {
                    // 更新最小的长度
                    if (r - l + 1 < minLen) {
                        minLen = r - l + 1;
                        minLenLeft = l;
                    }
                    // lrmap所记录s[l]即当前范围内最左端字符次数-1
                    // l位置右移
                    if (wordCountMap.find(s[l]) != wordCountMap.end()) {
                        --lrmap[s[l]];
                    }
                    ++l;
                }
            }
            return minLenLeft == -1 ? string() : s.substr(minLenLeft, minLen);
        };
};