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.

思路一:O(N*M)

滑动窗口,左右边界分别是 left 和 right (分别指向S中某一在T中也存在的字符)。

(1)判断当前窗口是否包含所有的T中字符,若没有,则更新 right 到下一个字符(在T中也存在的字符);

(2)若当前窗口已经包含了所有的T中字符,比较字符串长度是否最短更新字符串;然后更新 left 到下一个字符(在T中也存在的字符);

首先用数组记录T中每一个字符出现的次数,,即为 hash[256] ,然后记录目前的窗口中T中字符出现的次数,通过比较两数组的区别来判断该窗口是否有效。

即 hasAll 函数。

class Solution {
public:
    string minWindow(string S, string T) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(T.length()<=0) return T;
        if(S.length()<=0) return S;
    	vector hash(256,0);
        for(int i=0;i  count(256,0);
		//get the first char 
		while(rightright)  break;
			} else {
				rflag=true;
				right++;
			}
		}
        
		if(minlen==S.length()+1)
			return "";
        return S.substr(start,minlen);    
    }
    
    bool hasAll(string &T, vector &hash,vector &count) {
        for(int i=0;i


上述代码时间复杂度是 O(N*M) ,对大数据无法通过。 

思路二:O(N)

上述代码是可以继续优化的,因为在判断该窗口是否有效时,我们没有必要再遍历一遍T ,即上述代码的子函数:

bool hasAll(string &T, vector &hash,vector &count)

可以在生成窗口的过程中,记录当前已经生成了多少个T中的字符:如果 num=T.length() ,表示该窗口有效,可以更新最优解。

可以通过大数据。

class Solution {  
public:  
    string minWindow(string S, string T) {  

        int sLen = S.length();
        int tLen = T.length();
        // The hashtable used to record the num of letters of T in T and T in S
        int needToFind[256] = {0};
        for (int i = 0; i < tLen; i++)
            needToFind[T[i]]++;
        int hasFound[256] = {0};
        // The window for result: begin and end
        int minWindowLen = INT_MAX;
        int minWindowBegin;
        int minWindowEnd;
        // The num of letters in the window we have
        int count = 0;
        for (int begin = 0, end = 0; end < sLen; end++) {
            // skip characters not in T
            if (needToFind[S[end]] == 0) 
                continue;
            hasFound[S[end]]++;
            if (hasFound[S[end]] <= needToFind[S[end]]) 
                count++;
            // if window constraint is satisfied
            if (count == tLen) {
                // advance begin index as far right as possible,
                // stop when advancing breaks window constraint.
                while (needToFind[S[begin]] == 0 || hasFound[S[begin]]>needToFind[S[begin]]) {
                    if (hasFound[S[begin]] > needToFind[S[begin]])
                        hasFound[S[begin]]--;
                    begin++;
                }
                // update minWindow if a minimum length is met
                int windowLen = end - begin + 1;
                if (windowLen < minWindowLen) {
                    minWindowBegin = begin;
                    minWindowEnd = end;
                    minWindowLen = windowLen;
                } // end if
            } // end if
        } // end for
        if(count

其实上述代码还可以进一步优化:我们可以记录用一个 Queue 记录每次 right 停止的位置,因为 这些位置也是 left 将要停止的位置。

这样就 没必要进行 上述的 left 循环递增:

                // advance begin index as far right as possible,
                // stop when advancing breaks window constraint.
                while (needToFind[S[begin]] == 0 || hasFound[S[begin]]>needToFind[S[begin]]) {
                    if (hasFound[S[begin]] > needToFind[S[begin]])
                        hasFound[S[begin]]--;
                    begin++;
                }

可以直接弹出 Queue 中的一个 值作为 left 的值看是否满足条件。


你可能感兴趣的:(LeetCode)