题目:
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.
思路:双指针。前面的指针向前扩展到包含所有字符为止,这个时候有些字符可能有冗余,例如目标字符串"ab",源字符串"aab",当窗口包含所有字符时字符a存在冗余;又或者窗口末端存在无关字符,例如目标字符串"ab",源字符串"cab"。无论哪种情况,在这个时候窗口都有可能被压缩,因此用后面的指针向前判断,直到压缩到不能再压缩为止。
具体做法是,利用两个map,一个记录目标字符串每个字符的数量,另一个记录当前窗口中每个字符的数量,开始的时候两者是相等的。扩张的过程中,每当遇到目标字符串中的字符,则在当前窗口记录中将那个字符的数量减一。压缩的终止条件是,对于非相关字符,直接向前压缩,对于相关字符,判断剩余个数,如果小于0,说明有余量可以进行压缩,否则停止压缩,更新长度。
其中的一个问题是,刚开始的时候,不可以进行压缩,需要先把所有字符都包括,然后再压缩。具体做法是,利用一个变量count记录目标字符串字符个数,在扩张的过程中,如果当前字符在目标字符串中,且当前窗口记录中该字符数量 ≥ 0,说明此次扩展囊括了一个有效字符,则count值减一;反例是目标字符串"ab",源字符串"aab",当扩张的第二个a时,a已经是-1了,说明第二个不是有效字符。当count为0时,即可以开始压缩。从这个时间节点往后,扩张和压缩即是动态进行,每扩张一个字符,进行一次压缩,同时更新窗口。
class Solution {
public:
string minWindow(string S, string T) {
int len = INT_MAX;
string min_win = "";
vector<int> src_record(256, 0);
vector<int> cur_record(256, 0);
for (int i = 0; i < T.size(); ++i) {
src_record[T[i]]++;
cur_record[T[i]]++;
}
int front = 0;
int back = 0;
int count = (int)T.size();
for (; front < (int)S.size(); ++front) {
if (src_record[S[front]] > 0) { //the character is in T
cur_record[S[front]]--;
if (cur_record[S[front]] >= 0) {
count--;
}
}
if (count == 0) { //all characters in T are included
// shrink the current window
for (; back < front; ++back) {
if (src_record[S[back]] > 0) {
if (cur_record[S[back]] < 0) cur_record[S[back]]++; //can shrink
else break; //cannot shrink anymore
}
}
if (front - back + 1 < len) { //update
len = front - back + 1;
min_win = S.substr(back, front - back + 1);
}
}
}
return min_win;
}
};
总结:每个字符被两个指针访问一次,复杂度为O(n).