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(m*n2)
方法二:设置最短摘要起始位置winstart,最短摘要最终位置winend,winstart=0,winend = 0
1. 依次向后移动winend,每移动依次判断winstart~winend中的字串是否包含全部 T 串
2. 若第一次winend移动的位置,恰好使winstart~winend中的字符串包含全部T串(可能包含多个),这是依次向后移动winstart,直到到一个位置,恰好使第一次使winstart~winend中的字串恰好全部包含T串(因为再移动下一个位置,就不包含了),这是winstart~winend就是目前找到最短摘要之一。
3. 从1步骤开始,继续移动winend,寻找下一个最短摘要
注意:如果需要让时间复杂度达到O(n),那么必须空间换时间,需要使用哈希记录找到字符的个数。
代码如下:
1 class Solution { 2 public: 3 string minWindow(string S, string T) { 4 int mark[256] = {0}; //记录T中字符的种类及个数 5 int cnt[256] = {0}; //统计winstart~winend中字符的种类及个数 6 int hasfound = 0; //统计winstart包含T中字符的个数,每种达到上限就不记录 7 int winstart = 0, winend = 0; //窗口的起始和终止位置 8 int ansbegin = 0, ansend = 0x3fffffff; //记录结果,0x3fffffff表示没有找到 9 for(int i=0; i<T.length(); ++i) mark[ T[i] ]++; //预处理T中字符 10 while( winend < S.length() ) { 11 if( mark[ S[winend] ] ) { //如果是T中的字符 12 ++cnt[ S[winend] ]; //统计 13 if( cnt[ S[winend] ] <= mark[ S[winend] ] ) ++hasfound; //注意,很关键,如果统计的个数小于等于T中该字符的个数 14 if( hasfound == T.length() ) { //说明这是winstart~winend字符串全部包含了T 15 while( !mark[ S[winstart] ] //后移winstart,直到找到恰好使winstart~winend包含T 16 || cnt[ S[winstart] ] > mark[ S[winstart] ] ) { 17 if( cnt[ S[winstart] ] > mark[ S[winstart] ] ) --cnt[ S[winstart] ]; //某字符的个数多于T中该字符的个数 18 ++winstart; 19 } 20 if( winend-winstart < ansend-ansbegin ) { //如果窗口更小,记录结果中 21 ansbegin = winstart; 22 ansend = winend; 23 } 24 --cnt[ S[winstart] ]; //winstart向后移动,改变相应的数据结构 25 --hasfound; 26 ++winstart; 27 } 28 } 29 ++winend; 30 } 31 return ansend == 0x3fffffff ? string() : S.substr(ansbegin, ansend-ansbegin+1); 32 } 33 };