传送门:https://leetcode-cn.com/probl...
困难题,手动狗头
动态规划想了想感觉无法作为子问题求解,卒。
联想到滑动窗口,似乎是个可以解决的方法。
看到用例
S = "ADOBECODEBANC", T = "ABC"
1. 为T的每一个字符分配一个哈希表,记录其位于滑窗中的出现位置,滑窗中还没有该字符则赋值为0.考虑到0的问题,将赋值统一+1
2. 从S的首字符开始遍历,遍历过程中将遇到以下几种情况:
- S[i]∉T。即该字符不包含在T内,直接跳过
- S[i]∈T,map[s[i]]=0。即该字符包含在T内,且该数从前未出现过。则map[s[i]] = i
- S[i]∈T,map[s[i]]!=0。即该字符包含在T内,但该数已经出现。这里就比较复杂,简单来说分为如下几步:
1.更新map : map[s[i]] = i。
2.若该字符是该滑窗的首字符,则更新滑窗范围,这里就需要查询map中value最小的key。由于需要查找的是value,查询耗时O(n)
3. 遍历过程中,引入计数器count,若count = len(T),则每发生一次滑窗变动都要比较这个滑窗与当前最小滑窗的大小。
4. 遍历完成,返回最小滑窗。
出人意料,查看一下用例。原来T字符串是可以重复的。那你倒是早说啊┗|`O′|┛
重新审视一下代码过程:
思考过程不多说了,还是走了一点弯路。
再引入一个countMap记录每个字符的出现次数,遍历的三种情况做如下变换:
- S[i]∉T。即该字符不包含在T内,直接跳过
- S[i]∈T,map[s[i]]=0。即该字符包含在T内,且该数从前未出现过。则map[s[i]] = i
- S[i]∈T,map[s[i]]!=0,countMap[s[i]]>0。即该字符包含在T内,该字符出现过,但还没有出现完整。countMap[s[i]]--
- S[i]∈T,map[s[i]]!=0,countMap[s[i]]>0。即该字符包含在T内,该字符出现过,且出现完整。这里就比较复杂,简单来说分为如下几步:
1.更新map : map[s[i]] = 滑窗内第二次出现si。由于map只记录了第一次,这里需要遍历滑窗,查询耗时O(n)
2.若该字符是该滑窗的首字符,则更新滑窗范围,这里就需要查询map中value最小的key。由于需要查找的是value,查询耗时O(n)
class Solution {
public:
string minWindow(string s, string t) {
int lenofS = s.length();
int lenofT = t.length();
map<char,int> visitMap;
map<char,int> countMap;
char first = 0;
int begin=0,end=0;
int count = 0;
int min = 0;
int start=0,finish=0;
for(int i=0;i<lenofT;++i){
countMap[t[i]]++;
visitMap[t[i]] = 0;
}
while(end<lenofS){
//是目标数
if(visitMap.find(s[end])!=visitMap.end()){
if(!first){ first = s[end];begin=end;}
//窗口没有这个数
if(visitMap[s[end]] == 0){
visitMap[s[end]] = end+1;count++;
countMap[s[end]]--;
if(count==lenofT){
min = end-begin+1;start=begin;finish=end;
}
}
else if(countMap[s[end]]>0){
count++;
countMap[s[end]]--;
if(count==lenofT){
min = end-begin+1;start=begin;finish=end;
}
}
//有这个数,更新其地址
else if(visitMap[s[end]] != 0){
for(int i=visitMap[s[end]];i<=end;++i){
if(s[i]==s[end]){
visitMap[s[end]] = i+1;
break;
}
}
if(first==s[end]){
first = findSecond(visitMap);
begin = visitMap[first] - 1;
}
}
if(count == lenofT && min>end-begin+1) {
min = end - begin + 1;
start=begin;finish=end;
}
end++;
}
else{
if(!first) begin++;
end++;
cout<<"no"<<endl;
}
}
if(count!=lenofT) return "";
if(finish==0) s.substr(0,1);
return s.substr(start,finish-start+1);
}
char findSecond(map<char,int> &visitMap){
map<char,int>::iterator it;
it=visitMap.begin();
int min = it->second;char index = it->first;
for(;it!=visitMap.end();++it){
if(min ==0 || (it->second != 0 && it->second < min )){
min = it->second;index = it->first;
}
}
return index;
}
};
再看看有没有更好的方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。