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.
思路:
这道题最开始只有大概的想法,但是没有成型的算法,直到在网上搜了一些方案以后才做了出来。需要考虑的问题是:
1、如何判断S的子串是否包含了T的所有字母(应该在O(1)时间内)
2、如何在更新起始坐标。
比较直接的想法是用hash,因为字符的范围是0到255,所以可以用256的数组代替。使用toBeFilled表示每个字符需要填充的数目,hasFilled表示至今已经填充好的数目,一个整数count表示S的子串已经包含了T中的字符的数目。用left和right两个指针,首先遍历right,如果right指向的字符在T中存在,那么hasFilled加一,如果hasFilled小于等于toBeFilled的话,表示当前该字符还未填满,那么count加一。一直到count等于T的长度时表示S的子串已经包含T的所有字符。此时再将left尽量向right靠齐,靠齐的过程更新hasFilled,停止条件是如果hasFilled将要小于toBeFilled,更新此时的子串的起始位置,更新最小窗口的大小。因为left和right都至多遍历S的长度次,所以总复杂度是O(n)。
代码:
1 string minWindow(string S, string T) { 2 int ls = S.length(), lt = T.length(); 3 if(ls < lt) 4 return ""; 5 int toBeFilled[256] = {0}, hasFilled[256] = {0}; 6 int left, right, count = 0; 7 int begin, end, result = INT_MAX; 8 for(int i = 0; i < lt; i++){ 9 toBeFilled[T[i]]++; 10 } 11 for(left = 0, right = 0; right < ls; right++){ 12 if(toBeFilled[S[right]] == 0) 13 continue; 14 if(hasFilled[S[right]] < toBeFilled[S[right]]) 15 count++; 16 hasFilled[S[right]]++; 17 if(count == lt){ 18 while(true){ 19 if(toBeFilled[S[left]] == 0){ 20 left++; 21 continue; 22 } 23 if(hasFilled[S[left]] > toBeFilled[S[left]]){ 24 hasFilled[S[left]]--; 25 left++; 26 } 27 else{ 28 if(result > right - left + 1){ 29 begin = left; 30 end = right; 31 result = right - left + 1; 32 } 33 break; 34 } 35 } 36 } 37 } 38 if(count < lt) 39 return ""; 40 return S.substr(begin, result); 41 }