LeetCode算法系列:76. Minimum Window Substring

版权声明:由于一些问题,理论类博客放到了blogger上,希望各位看官莅临指教https://efanbh.blogspot.com/;本文为博主原创文章,转载请注明本文来源 https://blog.csdn.net/wyf826459/article/details/82885960

题目描述:

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).

Example:

Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"

Note:

  • If there is no such window in S that covers all characters in T, return the empty string "".
  • If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

算法实现

核心思路是维护两个索引Start 和 End(初值都为0),分别标识子串的开始位置和结束位置,通过一系列操作找到所有能够涵盖T所有字符的子串,然后找到最短串。

具体的我们要建立一个哈希映射,保存T中各个字符和其出现次数的关系映射,另外建立一个count保存当前窗口内的有效字符数,通过while循环来实现,具体在每一个while循环内,在当前位置

  1. 首先如果没有找到T中的字符,end++,继续往后找,直到找到一个T中的字符(m.count(s[end]))。
  2. 如果找到了T中的字母,则该字符在m中映射的value--(表示找到一个,需要的该字符的数量减一),当然可能有字母重复数大于其在T中的数量,即value减为负了,这样找出来的window包含多余重复字母可能不是最优,所以当value为负值时这个值也是需要记录的,另外如果value减一后仍然大于零表明这个字符是有效字符,要让count++
  3. 一旦找满单词(count = T.length()),这个时候Start到End的位置肯定是包含目标T串所有字符的子串W(即Window)。具体还要对这个window进行优化
    1. 排除不在T中的字符(其实就是让Start执行步骤1中类似的操作),缩小window大小
    2. 另一个方面,就是当window中出现重复的字符,这时,map中该字符的value为负了,我们可以在保证value值为非正的情况下向前移动start。
  4. 当找到一个符合要求的窗口后要对start进行操作,将start前移至下一个有效字符处,在移动start之前,要将当前start处的有效字符对应的value++, 同时count --(因为start后移后,其原位置处的有效字符被剔除窗口外)
class Solution {
public:
    string minWindow(string s, string t) {
        if(s.length() < t.length() || t.empty())return "";
        unordered_map<char, int> m;
        for(auto c:t)m[c] ++;
        int start = 0, end = 0, minstart = 0, minend = 0;
        int count = 0;
        int windowsize = -1, minwindowsize = INT_MAX;
        
        while(end < s.length()){
            
            while(end < s.length() && !m.count(s[end]))end ++;
            m[s[end]] --;
            if(m[s[end]] >= 0)
            {
                count ++;
                if(count == t.length()){
                    while(start != end){
                        while(!m.count(s[start]))start ++;
                        if(m[s[start]] < 0){
                            m[s[start]] ++;
                            start ++;
                            continue;
                        }
                        else
                            break;
                    }
                    windowsize = end - start + 1;
                    if(minwindowsize > windowsize){
                        minwindowsize = windowsize;
                        minstart = start;
                        minend = end;
                    }
                    m[s[start]] ++;
                    start ++;
                    while(start < end && !m.count(s[start]))start ++;
                    
                    count --;
                }
            }            
            end ++;
        }
        if(minwindowsize == INT_MAX)return "";
        return s.substr(minstart, minwindowsize);
    }
};

猜你喜欢

转载自blog.csdn.net/wyf826459/article/details/82885960