/*
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".
给定字符串S和字符串T,找到S中的最小窗口,其中将包含复杂度O(n)中T中的所有字符。
例如,
S =“ADOBECODEBANC”
T =“ABC”
最小窗口为“BANC”。
*/
滑动窗的暴力做法:
string minWindow(string s, string t) {
if (s.compare(t) == 0) return s;
int lens = s.size();
int lent = t.size();
map<char, int> mt;//存储t中的映射关系
map<char, int> m0;//存储t中的映射关系,置零
for (int i = 0; i < lent; i++){
if (mt.count(t[i]) == 0) {
mt.insert(pair<char, int>(t[i], 0));
m0.insert(pair<char, int>(t[i], 0));
}
mt[t[i]]++;
}
//构造m作为窗的判断条件
map<char, int> m = mt;
//截取的字符串长度,用作判断是否为最小窗口
int len = INT_MAX;
//结果
string minString;
//有效键值对个数
int cnt = m.size();
//窗的终点、起点
int end = 0;
int start;
bool flag = false;
for (end; end < lens; end++){
//若含有键,m中值--
if (m.count(s[end]) != 0){
m[s[end]]--;
//若该键对应值为0,有效键值对个数--
if (m[s[end]] == 0){
cnt--;
}
}
//当有效键值对个数为0时,end为窗的终点
if (cnt == 0){
//由终点往前找起点
start = end;
//避免值为负数的情况
m = m0;
//起点找到的判断条件是有效键值对的个数恢复到t中有效键值对的个数
while (cnt != mt.size()){
//如果包含该键
if (m.count(s[start]) != 0){
//值++
//如果值恢复为t中的值,有效键值对个数++
if (++m[s[start]] == mt[s[start]])
{
cnt++;
}
}
//如果有效键值对的个数恢复到了t中有效键值对的个数
//找到了窗的起点start
if (cnt == mt.size()){
//如果此时的窗比之前的小,保存窗字符串
if (len > end - start + 1){
len = end - start + 1;
minString = s.substr(start,len);
}
//释放start处的值
//不管是否为最小窗,完成了一次start,end的截取后
flag = true;
m = m0;
m[s[start]]++;
}
//未找到start,继续向前查找
start--;
}
}
if (flag){
//释放后有效键值对个数为1
cnt = 1;
flag = false;
}
}
return minString;
}
能解决问题,但是超时了。
讨论中的做法如下,
关键还是有效键值对个数这个值
string minWindow(string s, string t){
if (s.compare(t) == 0) return s;
int lens = s.size();
int lent = t.size();
map<char, int> mt;//存储t中的映射关系
for (int i = 0; i < lent; i++){
if (mt.count(t[i]) == 0) {
mt.insert(pair<char, int>(t[i], 0));
}
mt[t[i]]++;
}
int cnt = mt.size();
int end = 0;
int start = 0;
int head = 0;
int len = INT_MAX;
for (end; end < lens; end++){
char tem = s[end];
if (mt.count(tem) != 0){
mt[tem]--;
if (mt[tem] == 0){
cnt--;
}
}
while (cnt == 0){
char tem = s[start];
if (mt.count(tem) != 0){
mt[tem]++;
if (mt[tem]>0){
cnt++;
if (end - start+1 < len){
len = end - start+1;
head = start;
}
}
}
start++;
}
}
if (len == INT_MAX) return "";
return s.substr(head, len);
}