76. 最小覆盖子串

思路1(会超时)

#include<bits/stdc++.h>  
using namespace std;  
typedef long long int64;  
  
class Solution {  
public:  
    bool check(unordered_map<char, int> give, unordered_map<char, int> need) {  
        /**  
         * 检查是否满足条件  
         */        
        for (auto &[k, v]: need) {  
            if (v > give[k]) return false;  
        }  
        return true;  
    }  
  
    string minWindow(string s, string t) {  
        /**  
         * 思路:初始时i,j都在s开头,若不满足,扩大区间(j++),若满足,则缩小区间(i--),这个过程中会存在最小长度的满足条件的区间  
         */        int n = s.length(); // c++ 不能使用int 比较 unsigned        unordered_map<char, int> ct, cs;  
        for (char c: t) ++ct[c];  
        int i = 0, j = -1;  
        int res = s.length() + 1;  
        string r= "";  
        while (j < n) {  
            while (j < n and !check(cs, ct)) {  
                ++cs[s[++j]];  
            }  
            while (j < n and check(cs, ct)) {  
                if (j - i < res) {  
                    res = j - i;  
                    r = s.substr(i,j-i+1);  
                }  
                --cs[s[i++]];  
            }  
        }  
        return r;  
        /*  
         * 然而这样也会超时  
         */    
         }  
};

优化想法:在窗口收缩的时候只需要比较左边被踢出的那个字符,就能剪枝部分运算

class Solution {  
public:  
    static bool check(unordered_map<char, int> &give, unordered_map<char, int> &need, const char toCheck) {  
        /**  
         * 检查是否满足条件  
         */        if (toCheck == '*') {  
            for (auto &[k, v]: need) {  
                if (v > give[k]) return false;  
            }  
        } else if (need[toCheck] > give[toCheck]) {  
            return false;  
        }  
        return true;  
    }  
  
    string minWindow(string s, string t) {  
        /**  
         * 思路:初始时i,j都在s开头,若不满足,扩大区间(j++),若满足,则缩小区间(i--),这个过程中会存在最小长度的满足条件的区间  
         */        int n = s.length(); // c++ 不能使用int 比较 unsigned        unordered_map<char, int> ct, cs;  
        for (char c: t) ++ct[c];  
        int i = 0, j = -1;  
        int res = s.length() + 1;  
        string r= "";  
        while (j < n) {  
            while (j < 0 or (j < n and !check(cs, ct, '*'))) {  
                ++cs[s[++j]];  
            }  
            while (i-1 < 0 ?  (j < n and check(cs, ct, '*')) : (j < n and check(cs, ct, s[i-1]))) {  
                if (j - i < res) {  
                    res = j - i;  
                    r = s.substr(i,j-i+1);  
                }  
                --cs[s[i++]];  
            }  
        }  
        return r;  
        /*  
         * 然而这样也会超时  
         */    }  
};

这样还是会内存超限

最终优化:扁平化

class Solution {  
public:  
    bool check(unordered_map<char, int> give, unordered_map<char, int> need) {  
        /**  
         * 检查是否满足条件  
         */        
         for (auto &[k, v]: need) {  
            if (v > give[k]) return false;  
        }  
        return true;  
    }  
  
    string minWindow(string s, string t) {  
        /**  
         * 思路:初始时i,j都在s开头,若不满足,扩大区间(j++),若满足,则缩小区间(i--),这个过程中会存在最小长度的满足条件的区间  
         */        
         // eg. s:"ADOBECODEBANC", t:"ABC"        
         if (t.empty() or s.empty()) {  
            return "";  
        }  
  
        array<int, 128> need = {0}, window = {0};  
        int required = 0;   // 需要满足的字符的个数  
        for (char c: t) {  
            if (need[c] == 0) {  
                ++required;  
            }  
            ++need[c];  
        }  
        // required: 3;  如果t是"AABC",则required也为3,只有3种字符  
        int formed = 0; // 已满足的字符的个数  
        int l = 0;  
        int bestLen = INT_MAX, bestL = 0;  
        for (int r = 0; r < (int)s.size(); ++r) {  
            char c = s[r];  
            ++window[c];  
            if (need[c] > 0 and window[c] ==  need[c]) {  
                ++formed;  
            }  
            while (formed == required) {  
                // 已经满足条件了  
                if (r - l + 1 < bestLen) { /* 这个过程会存在最短的区间 */                    bestLen = r - l + 1;  
                    bestL = l;  
                }  
                // 收缩窗口,扔掉最左的字符  
                char cl = s[l];  
                --window[cl];  
                if (need[cl] > 0 and window[cl] < need[cl]) --formed;  
                ++l;  
            }  
        }  
        return bestLen == INT_MAX ? "" : s.substr(bestL, bestLen);  
    }  
};

本站由 Rizxfrog 使用 Stellar 创建。