题目描述:
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.
思路是双指针分别记录窗口的左右端点,右指针不断右移,每当遇到T中的元素时收缩左端点到最小。那么这题的主要问题就是如何收缩左端点。一开始想的有点麻烦,用map<char, vector>记录下每个元素的坐标,当右端点遇到T中元素时将最小的去掉,再push进当前坐标。后来想到,因为不考虑顺序,只要记录窗口内元素的个数是否比T中对应元素的个数多就可以了,又重新写了下。
两种方法都可以AC,时间也差不多,可能还是测试数据不够大吧,因为vector中删除操作为O(n)复杂度,数组占用空间也更多,数据再大一点第一种方法可能就通不过了。
代码如下:
class Solution {
public:
string minWindowII(string S, string T) {
unordered_map<char, int> count, curr;
int left(0), right(S.length() - 1), l(-1);
for (int i = 0; i < T.length(); i++)
count[T[i]]++;
curr = count;
for (int i = 0; i < S.length(); i++){
if (count.count(S[i])){
if (l < 0)
l = i;
count[S[i]]--;
curr[S[i]]--;
if (count[S[i]] == 0)
count.erase(S[i]);
}
else if (curr.count(S[i])){
curr[S[i]]--;
while (!curr.count(S[l]) || curr[S[l]] < 0){
if (curr.count(S[l]))
curr[S[l]]++;
l++;
}
}
if (count.empty() && i - l < right - left){
left = l;
right = i;
}
}
if (!count.empty())
return "";
return S.substr(left, right - left + 1);
}
string minWindowI(string S, string T) {
unordered_map<char, int> count;
unordered_map<char, vector<int>> index;
int left(0), right(S.length() - 1);
for (int i = 0; i < T.length(); i++)
count[T[i]]++;
int l(-1);
for (int i = 0; i < S.length(); i++){
if (count.count(S[i])){
if (l < 0)
l = i;
index[S[i]].push_back(i);
count[S[i]]--;
if (!count[S[i]])
count.erase(S[i]);
}
else if (index.count(S[i])){
vector<int> *v = &index[S[i]];
v->erase(v->begin());
v->push_back(i);
if (S[i] == S[l])
do{
l++;
} while (!(index.count(S[l]) && index[S[l]][0] == l));
}
if (count.empty() && i - l < right - left){
left = l;
right = i;
}
}
if (!count.empty())
return "";
return S.substr(left, right - left + 1);
}
};