题目:
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""
。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案。
坑点:
1.在S中找到包含T中所有字母的子串,这个子串并不仅仅是要包含所有T中出现的字母种类,也要包含相对应的数量,如果T中有3个a,那么S的这个子串也需要有3个a才符合条件。
2.T的长度可能大于S的长度
思路:
1.如果T的长度大于S的长度,直接返回空。
2.用一个向量vector记录字符串T中出现的字母种类,用一个数组ans记录,T中每一个字母分别出现的次数。
3.如果判断s中的一个子串是否符合要求呢?如果对vetor中出现的元素(就是T字符串的字母种类),s子串中,这个字母出现的次数(用ch数组记录)都大于ans数组中的次数,则说明S这个子串符合要求。
4.对于S而言,用一个头指针i,尾指针j,s[j,i]之间就是s的一个子串,初始时i=j=0,然后i向前移动,直到s[j,i]符合要求,记录下此时子串的长度,如果长度小于原先记录的值,那么更新答案。然后往前移动j,这时候子串是否依然符合要求,如果符合,同样记得更新答案,并且j指针继续往前移动,直到不符合为止。
5.如果j指针不符合了,那么移动i指针,直到s[j,i]继续符合条件,此时,重复流程4,直到i指针到达S的末尾,答案在指针移动途中已经更新。
代码:
class Solution {
public:
int ch[300];
int ans[300];
vector<int>ve;
int num;
int maxx = 1e9;
bool pan(){
int num = 0;
int sz = ve.size();
for(int i=0;i<sz;i++){
if(ch[ve[i]]<ans[ve[i]]){
return false;
}
}
return true;
}
string minWindow(string s, string t) {
int len = t.length();
memset(ans,0,sizeof(ans));
for(int i=0;i<len;i++){
ans[t[i]]++;
}
for(int i=0;i<300;i++){
if(ans[i]){ve.push_back(i);}
}
int len2 = s.length();
if(len2<len)return "";
memset(ch,0,sizeof(ch));
int ma = maxx;
int sta,en,i,j;
for(i=0,j=0;i<len2;i++){
ch[s[i]]++;
while(pan()&&i>=j){
if(ma>i-j){
sta = j;
en = i;
ma = i-j+1;
}
ch[s[j]]--;
j++;
}
}
if(ma==maxx)return "";
else return s.substr(sta,ma);
}
};
以上.