我太菜了,这题做不出来,超时代码:
class Solution {
public:
string minWindow(string s, string t) {
int n=s.size();
int m=t.size();
if(n<m) return "";
bool first=true;//第一次标记
string res="";
map<char,int> mapt;//储存个字符及其个数
for(int i=0;i<m;i++) mapt[t[i]]++;
/*for(auto a=mapt.begin();a!=mapt.end();a++){
cout<<a->first<<" "<<a->second<<endl;
}
cout<<endl;*/
for(int i=0;i<=n-m;i++){
if(mapt[s[i]]>0){//子串首字母在t中存在
//cout<<s[i]<<" "<<i <<" ";
string temp=jude(mapt,s,i,m);
//cout<<temp<<endl;
if(first && temp=="") return "";//不存在满足的子串
else if(temp!="" &&(temp.size() < res.size() || first)){//如果新的子串比原来的短 或者 第一个子串
res=temp;
first=false;
}
int k=temp.size();
//while(i+k<n && mapt[s[i+k]]==0) i++;//节约时间,子串后一个t中不存在,i++(无需循环调用jude函数)
}
}
return res;
}
string jude(map<char,int> mapt,string s,int i,int m){
int j=i;
int count=m;//记录未涵盖m的字符个数 因为首字母已匹配 所以减1
while(j<s.size() && count>0){
if(mapt.count(s[j])) {
mapt[s[j]]--;
count--;
}
j++;
}
if(count==0) return s.substr(i,j-i);//返回满足子串 注意此时j的下标为子串后面的一个字符的下标
else return "";//不存在满足的子串
}
};
参考评论区佬们的答案:
class Solution {
public:
string minWindow(string s, string t) {
int n=s.size(), m=t.size();
if(n<m) return "";
string res="";//最短子串
map<char,int> ms, mt;
for(int i=0;i<m;i++) mt[t[i]]++;//初始化
int l=0;//子串的左下标
int count=0;//有效字符的个数
for(int i=0;i<n;i++){
ms[s[i]]++;
if(ms[s[i]]<=mt[s[i]]) count++;//增加有效字符
while(l<i && ms[s[l]]>mt[s[l]]){//从左边删除冗余部分
ms[s[l]]--;
l++;
}
if(count==m){//前面是边增有效字符边删除冗余部分
if(res=="" || i-l+1<res.size())
res=s.substr(l,i-l+1);
}
}
return res;
}
};
如果要改进,可将map<char,int> ms, mt; 换成 int ms[‘z’-‘A’+1], mt[‘z’-‘A’+1]来节约内存。