找出包含子串的最小窗口
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.
题目意思:
给定一个字符串S和一个字符串T,不要求T的顺序,从S中找出包含T中字符的长度最小的子串,即最小窗口子串。要求算法时间复杂度为O(n)。
解题思路:
这题的考点是两个指针,一个begin在前,一个end在后,当begin和end都包含了T字符串中字符的时候,计算此时begin和end之间的距离,即为一个窗口子串的长度。当end遍历到S的最后时,得到所有算出来的窗口子串中长度最大的那个,即为答案。因为两个指针都从头到尾遍历了一遍,所以时间复杂度是O(n)。
还有一个小技巧就是,怎么才能知道已经包含了所有的字符呢?
可以像桶排序那样,建立一个很大的数组,以T中的字符(ASCI码)为下标的位置设为1,其他为0.
再建立一个很大的数组,遍历S中字符的时候,遍历到一个字符以那个字符为下标设置一个1,当刚好T那个数组中是1的位置对应S的那个数组相应位置全都是非0的时候,就全部包含了T中的字符拉!
至于那个数组多大,就设置为255,包含unicode字符。
代码如下:
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 using namespace std; 5 6 class Solution { 7 public: 8 string minWindow(string S, string T) { 9 vector<int> s_vec(256,0); 10 vector<int> t_vec(256,0); 11 int lp = -1, rp = -1, answer = 0x7fffffff, begin = 0, lack = T.size(); 12 //将T中字符对应位置设置成1 13 for(int i = 0;i < T.size();i++){ 14 t_vec[T[i]]++; 15 } 16 for(int end = 0; end < S.size(); end++){ 17 //负责移动右边的i,直到包含了所有T中的字符 18 if(s_vec[S[end]] < t_vec[S[end]]) 19 lack--; 20 s_vec[S[end]]++; 21 22 if(lack == 0){ 23 //负责移动左边的lb 24 while( begin < end && s_vec[S[begin]] > t_vec[S[begin]]){ 25 s_vec[S[begin]]--; 26 begin++; 27 } 28 //记录下此时的长度和lb,i的位置 29 if(answer > end - begin + 1){ 30 answer = end - begin + 1; 31 lp = begin; 32 rp = end; 33 } 34 //lb向右移一个 35 while(lack == 0){ 36 s_vec[S[begin]]--; 37 begin += 1; 38 lack += 1; 39 } 40 } 41 } 42 return lp==-1?"":S.substr(lp,rp-lp+1); 43 } 44 }; 45 46 int main(){ 47 Solution s; 48 string S = "ADOBECODEBANC"; 49 string T = "ABC"; 50 string r = s.minWindow(S,T); 51 cout << r << endl; 52 getchar(); 53 }