题目大意:给定字符串S和T,在S串中找出一个最小子串,这个子串包含T的所有字符。
解题思路:hashtable.
用一个hashtable来保存T中每次字符的出现次数。
用另一个hashtable来保存S中包含T中字符的出现次数。
重头开始扫描S,若扫描到当前位置包含了T中所有的字符,则缩小窗口直到不能包含T的所有字符为止,若小于之前保存的最小窗口,则保存这个当前窗口。
class Solution {
public:
string minWindow(string S, string T) {
if(S.size() < T.size())
return "";
const int charSize = 256;
int foundLen = 0;
vector<int> TStrCnt(charSize, 0);
vector<int> foundStr(charSize, 0);
int start = -1;
int winStart = -1, winEnd = S.size();
for(int i = 0; i < T.size(); i++) {
TStrCnt[T[i]]++;
}
for(int i = 0, start = 0; i < S.size(); i++) {
if(TStrCnt[S[i]] > 0) {
foundStr[S[i]]++;
if(foundStr[S[i]] <= TStrCnt[S[i]])
foundLen++;
if(foundLen == T.size()) {
while(TStrCnt[S[start]] == 0 || foundStr[S[start]] > TStrCnt[S[start]]) {
if(foundStr[S[start]] > TStrCnt[S[start]])
foundStr[S[start]]--;
start++;
}
if(winEnd - winStart > i - start) {
winStart = start;
winEnd = i;
}
foundStr[S[start]]--;
start++;
foundLen--;
}
}
}
return winStart == -1 ? "" : S.substr(winStart, winEnd - winStart +1);
}
};
另一种优化版
http://www.cnblogs.com/TenosDoIt/p/3461301.html
用队列保存窗口起始位置。
class Solution {
public:
string minWindow(string S, string T) {
if(S.size() < T.size())
return "";
const int charSize = 256;
int foundLen = 0;
vector<int> TStrCnt(charSize, 0);
vector<int> foundStr(charSize, 0);
queue<int> que;
int winStart = -1, winEnd = S.size();
for(int i = 0; i < T.size(); i++) {
TStrCnt[T[i]]++;
}
for(int i = 0; i < S.size(); i++) {
if(TStrCnt[S[i]] > 0) {
que.push(i);
foundStr[S[i]]++;
if(foundStr[S[i]] <= TStrCnt[S[i]])
foundLen++;
if(foundLen == T.size()) {
int k = que.front();
while(foundStr[S[k]] > TStrCnt[S[k]] && !que.empty()) {
foundStr[S[k]]--;
que.pop();
if(!que.empty())
k = que.front();
}
if(winEnd - winStart > i - k) {
winStart = k;
winEnd = i;
}
foundStr[S[k]]--;
que.pop();
foundLen--;
}
}
}
return winStart == -1 ? "" : S.substr(winStart, winEnd - winStart +1);
}
};