[LeetCode] 76. 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.

首先建立两个HashMap或Array(int),初始256个字符出现的次数都为0,一个TMap用来统计T中所有字母的个数,另一个SMap用来统计S中出现的T中含有的字母个数。使用双指针来动态维护一个窗口区间,尾指针不断向后扫,当扫到的字符在TMap中存在,说明找到了一个字符,把它添加到SMap中。当有一个窗口包含了所有T的字符后,就收缩头指针,直到保证窗口包含T中字母不能再收缩为止,比较这个窗口,记录所有可能的情况中窗口最小的。

因为ASCII字符数量只有256个,所以HashMap可以用数组来代替,比如字符串"aabb",array[97] = 2,array[98] = 2。

Java:

public class Solution {
    public String minWindow(String S, String T) {
        int[] srcHash = new int[256];
        for(int i = 0; i < T.length(); i++){
            srcHash[T.charAt(i)]++;
        }
        int start = 0,i= 0;
        int[] destHash = new int[256];
        int found = 0;
        int begin = -1, end = S.length(), minLength = S.length();
        for(start = i = 0; i < S.length(); i++){
            destHash[S.charAt(i)]++;
            // 加1后这个字符的数量不超过目标串中该字符的数量,则找到了一个匹配字符
            if(destHash[S.charAt(i)] <= srcHash[S.charAt(i)]) found++;
            // 找到的匹配字符数等于目标串长度,说明找到了一个符合要求的子串    
            if(found == T.length()){
                // 将开头没用的都跳过,没用是指该字符出现次数超过了目标串中出现的次数,并把它们出现次数都减1
                while(start < i && destHash[S.charAt(start)] > srcHash[S.charAt(start)]){
                    destHash[S.charAt(start)]--;
                    start++;
                }
                // 这时候start指向该子串开头的字母,判断该子串长度
                if(i - start < minLength){
                    minLength = i - start;
                    begin = start;
                    end = i;
                }
                // 把开头的这个匹配字符跳过,并将匹配字符数减1
                destHash[S.charAt(start)]--;
                found--;
                // 子串起始位置加1,开始看下一个子串了
                start++;
            }
        }

        return begin == -1 ? "" : S.substring(begin,end + 1);
    }
}

Python:

class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        current_count = [0 for i in xrange(256)]
        expected_count = [0 for i in xrange(256)]
        
        for char in t:
            expected_count[ord(char) - ord('a')] += 1
        
        i, count, start, min_width, min_start = 0, 0, 0, float("inf"), 0
        while i < len(s):
            current_count[ord(s[i]) - ord('a')] += 1
            if current_count[ord(s[i]) - ord('a')] <= expected_count[ord(s[i]) - ord('a')]:
                count += 1
            
            if count == len(t):
                while expected_count[ord(s[start]) - ord('a')] == 0 or 
                      current_count[ord(s[start]) - ord('a')] > expected_count[ord(s[start]) - ord('a')]:
                    current_count[ord(s[start]) - ord('a')] -= 1
                    start += 1
                
                if min_width > i - start + 1:
                    min_width = i - start + 1
                    min_start = start
            i += 1
                    
        if min_width == float("inf"):
            return ""
        
        return s[min_start:min_start + min_width]

 C++:

class Solution {  
public:  
    string minWindow(string S, string T)   
    {  
        if(S.empty() || S.size() < T.size())  
            return "";  
        int appeared_count[256] = {0};  
        int expected_count[256] = {0};  
        for(int i = 0 ; i < T.size() ; i++)  
            expected_count[T[i]]++;  
        int minWidth = INT_MAX , min_start = 0; 
        int wnd_start = 0; 
        int appeared = 0; //appeared记录S中出现的T中的字符的个数,当appeared==T.size()时,说明找到一个符合条件的  
        for(int wnd_end = 0 ; wnd_end < S.size() ; wnd_end++)  
        {  
            if(expected_count[S[wnd_end]] > 0)  
            {  
                appeared_count[S[wnd_end]]++;  
                if(appeared_count[S[wnd_end]] <= expected_count[S[wnd_end]])  
                    appeared++; //当字符S[wnd_end]出现的次数不大于T中出现次数时,appeared才++  
            }  
            if(appeared == T.size())  
            {  
                while(appeared_count[S[wnd_start]] > expected_count[S[wnd_start]] ||   
                expected_count[S[wnd_start]] == 0)  
                {  
                    appeared_count[S[wnd_start]]--;  
                    wnd_start++;  
                }  
                if(minWidth > (wnd_end - wnd_start + 1))  
                {  
                    minWidth = wnd_end - wnd_start + 1;  
                    min_start = wnd_start;  
                }  
            }  
        }  
        if(minWidth == INT_MAX)  
            return "";  
        else  
            return S.substr(min_start , minWidth);  
    }  
}; 

  

类似题目:

[LeetCode] 3.Longest Substring Without Repeating Characters 最长无重复子串

[LeetCode] 159. Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串

[LeetCode] 340. Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串

[LeetCode] 727. Minimum Window Subsequence 最小窗口子序列  

All LeetCode Questions List 题目汇总

原文地址:https://www.cnblogs.com/lightwindy/p/8523054.html