首页 > 代码库 > 【leetcode刷题笔记】Minimum Window Substring
【leetcode刷题笔记】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.
题解:参考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 }