標籤:style blog http color os strong io 2014
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.
題解:參考leetcode給出的解答,實現了O(n)的演算法。
用到的主要變數如下:
設定一個Map:ToFind記錄T中出現的字元的種類和個數,我們需要在S中找到這些字元。
設定另一個Map:hasFound記錄當前視窗中包含的字元的種類和個數。
這兩個Map,結合一個變數count——在當前視窗中找到的T中的字元個數,我們就可以判斷當前視窗是否包含T中所有的字元了。
演算法的主要過程如下:
- 當前視窗的起始和結束位置都在S(0)處;
- 當視窗中沒有包含T中所有的字元時(count<T.length),擴充視窗的右端end,直到視窗中包含了T中所有的變數。
- 此時視窗不一定是最小的,因為左端還有可能縮排,根據視窗的左端變數begin所指的元素,把視窗的左端儘可能右移。
- 得到一個包含T的視窗,跟最小的視窗比較,如果比最小的視窗小,就更新最小的視窗。
舉個例子:S = "acbbaca" , T = "aba"。
如所示,end從初始的位置擴充到下面的圖中的位置時候,視窗包含了T中所有的字元,而且begin也無法挪動了,此時得到一個最小視窗長度為5;
接下來繼續移動end直到下一個包含在T裡面的元素處(見第二幅圖),然後把begin儘可能往右移動(見第三幅圖),得到一個新的當前最小視窗baca,由於它比最小視窗acbba短,所以更新最小視窗為baca。演算法結束。
所以我們可以看出begin只有在找到T的時候才右移收縮視窗,而end一直後移。在找到第一個視窗後,end每移動到一個T裡麵包含的元素處,就會有一個新的視窗(比如上述end從索引為4的地方挪動到索引為6的地方)。
代碼如下:
1 public class Solution { 2 public String minWindow(String S, String T) { 3 HashMap<Character, Integer> needToFind = new HashMap<Character, Integer>(); 4 HashMap<Character, Integer> hasFound = new HashMap<Character, Integer>(); 5 int count = 0; 6 7 for(int i = 0;i < T.length();i++){ 8 char ch_t = T.charAt(i); 9 if(!needToFind.containsKey(ch_t)){10 needToFind.put(ch_t, 1);11 hasFound.put(ch_t, 0);12 }13 else {14 needToFind.put(ch_t, needToFind.get(ch_t)+1);15 }16 }17 18 int minWindowBegin = -1;19 int minWindowEnd = S.length();20 int minWindowLen = S.length();21 for(int begin = 0,end = 0; end < S.length();end++){22 char char_end = S.charAt(end);23 //skip character not in T24 if(!needToFind.containsKey(char_end))25 continue;26 hasFound.put(char_end, hasFound.get(char_end)+1);27 if(hasFound.get(char_end) <= needToFind.get(char_end))28 count++;29 30 if(count == T.length()){31 //narrow down the window as much as possible32 char char_begin = S.charAt(begin);33 while(!needToFind.containsKey(char_begin) || hasFound.get(char_begin) > needToFind.get(char_begin)){34 if(needToFind.containsKey(char_begin) && hasFound.get(char_begin) > needToFind.get(char_begin)){35 hasFound.put(char_begin, hasFound.get(char_begin)-1);36 }37 begin++;38 char_begin = S.charAt(begin);39 }40 41 int windowLen = end - begin + 1;42 if(windowLen <= minWindowLen){43 minWindowBegin = begin;44 minWindowEnd = end;45 minWindowLen = windowLen;46 }47 48 }49 }50 51 if(count == T.length()){52 StringBuffer sbBuffer = new StringBuffer();53 for(int i = minWindowBegin;i<=minWindowEnd;i++)54 sbBuffer.append(S.charAt(i));55 return sbBuffer.toString();56 }57 else58 return ""; 59 }60 }