现在的位置: 首页 > 综合 > 正文

LeetCode题解:Minimum Window Substring

2019年07月25日 ⁄ 综合 ⁄ 共 2171字 ⁄ 字号 评论关闭

Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the emtpy string"".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

思路:

题目对时间复杂度要求很高。首先要考虑简化T和S的运算。T中只要统计不同字母个数即可,而S中只有相应T的字母及其位置才有意义。所以先把这些内容抽出来放到一个hash中简化计算。然后考虑的是如何在S中寻找满足T的子串。这时可以使用两个指针指向简化后的S(记作S'),一个向前移动(r_iter),一个不动(l_iter)。在r_iter向前移动到l_iter和r_iter之间的内容满足要求时,检查是否比之前找到的子串短。之后再移动l_iter,并相应的移动r_iter直到找到下一个满足要求的子串。略微复杂的是,可能在这一段中,一个字母被用的次数多于T中给出的次数,这时需要将多余的字母个数计数,但是却又不能计算在和T比较的字母长度之中。这样,扫视一次T和S可以看作O(2n),而两个指针的扫视是O(n)。总共时间是O(3n)。

题解:

class Solution {
public:
    string minWindow(string S, string T) {
        enum { CHR_MAX = 256 };                                                                            
                                                                                                           
        // Empty input
        if (T == "" || S == "")
            return string("");
    
        array<int, CHR_MAX> TUsage; // character count in string T
    
        // setup the T list to hash the characters
        fill(begin(TUsage), end(TUsage), 0);
        for(auto ch : T)    // hash all used characters
            ++TUsage[ch];
    
        const size_t T_CHARS = T.size();
    
        vector<pair<char, size_t>> SUsage; // characters from T in S
        size_t offset = 0;
        for(auto ch : S)
        {
            if (TUsage[ch] != 0) 
                SUsage.push_back(make_pair(ch, offset)); 
            ++offset;
        }
    
        // minimum window range
        size_t min_l = 0, min_r = S.size()+1;
        size_t old_minl = min_r - min_l;
    
        // record the current window character usage
        size_t tchar_used = 0;
        array<int, CHR_MAX> ChUsage;
        fill(begin(ChUsage), end(ChUsage), 0);
    
        // the search window left/right iterator
        vector<pair<char, size_t>>::const_iterator l_iter = SUsage.begin();
        vector<pair<char, size_t>>::const_iterator r_iter = l_iter;
        size_t new_minl;
    
        // scan the SUsage
        while(l_iter < SUsage.end())
        {
            while(r_iter < SUsage.end() && tchar_used < T_CHARS)
            {
                char ch = r_iter->first;
    
                ++ChUsage[ch];
    
                // register the used character
                if (ChUsage[ch] <= TUsage[ch])
                    ++tchar_used;
    
                ++r_iter;
            }
    
            if (tchar_used == T_CHARS)
            {
                // verify if it is the minimum window
                new_minl = (r_iter - 1)->second - l_iter->second + 1;
                if (new_minl < old_minl)
                {
                    min_r = (r_iter - 1)->second;
                    min_l = l_iter->second;
                    old_minl = new_minl;
                }
    
                // now do the next iteration
                --ChUsage[l_iter->first];
                if (ChUsage[l_iter->first] < TUsage[l_iter->first])
                    --tchar_used;
                ++l_iter;
            }
            else
                break;  // cannot find any more windows
        }
    
        if (min_r == S.size() + 1)
            return string("");
        else
            return S.substr(min_l, min_r - min_l + 1);
    }
};

抱歉!评论已关闭.