用两个指针分别记录窗口的左右边界,移动指针时忽略那些出现在S种但是没有出现在T中的字符
1. 扩展窗口。向右移动右指针,当窗口内的字符即将多于T内的字符时,停止右移
2. 收缩窗口。向右调整左指针,当窗口内的字符即将少于T内的字符时,停止右移
3. 统计结果。如果窗口内的字符包含了T内的所有字符,且窗口更小,更新最小窗口
4. 继续下一个周期(返回1)
大致思路就是这样了,在具体实现中我用了一个left变量记录当前还未完全包含的非重字符数量,比如当前窗口还差2个a和3个b,则left=2,这样,当left=0时就知道已经包含了所有T的字符。
代码:
1 string minWindow(string S, string T) { 2 map<char, int> tMap; 3 map<char, int> windowMap; 4 int sLen = S.length(); 5 int tLen = T.length(); 6 string window = ""; 7 int left = 0; 8 9 for (int i = 0; i < tLen; i++) 10 tMap[T[i]]++; 11 left = tMap.size(); 12 13 // 扩展 14 for (int l = 0, r = 0; r < sLen;) { 15 for (bool shrink = false; r < sLen && !shrink; r++) { 16 if (tMap.find(S[r]) != tMap.end()) { 17 windowMap[S[r]]++; 18 if (windowMap[S[r]] == tMap[S[r]]) 19 left--; 20 shrink = windowMap[S[r]] >= tMap[S[r]]; 21 } 22 } 23 24 // 收缩 25 for (; l < r; l++) { 26 if (tMap.find(S[l]) != tMap.end()) { 27 if (windowMap[S[l]] <= tMap[S[l]]) 28 break; 29 windowMap[S[l]]--; 30 } 31 } 32 33 if (!left && (window.empty() || window.length() > r - l)) 34 window = S.substr(l, r - l); 35 } 36 37 return window; 38 }