题目描述
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""
。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案。
思路及代码
class Solution {
public:
string minWindow(string s, string t) {
if(s==""||t=="")
return "";
int n1 = s.size();
int n2 = t.size();
map<char,int> m; //利用map来统计t字符串中每个元素出现的个数
for(int i=0;i<n2;i++){
if(m.find(t[i])!=m.end()) //!=m.end()证明找到了该元素
m[t[i]]++;
else
m[t[i]]=1;
}
int count = 0; //统计t字符串是否被全部覆盖了
int left = 0; //left和right用来遍历s字符串,right和left的差为最小长度
int right = 0;
int minvalue = INT_MAX; //minvalue表示最小区间长度
int minLeft = 0;
int minRight = 0; //这两个变量用来存储到目前为止最小长度的两个边界
for(;right<n1;right++){
if(m.find(s[right]) != m.end()){
if(m[s[right]]>0){
count++; //如果满足条件就count++,表示已经匹配了t中的一个字符
}
m[s[right]]--;
}
while (count == n2){ //count如果不等于n2就for循环下一层,right右移
if (right - left < minvalue){
minvalue = right - left; //求当前长度
minLeft = left;
minRight = right;
}
if (m.find(s[left]) != m.end()){ //判断所删减的字符如果在map中
if (m[s[left]] >= 0)
count --; //m[s[left]]>=0时,证明该字符为必不可少的了,count--意为跳出此while循环
m[s[left]]++; //map中有这个字符,每次移动left的时候就要+一次,因为当初right的时候-了
}
left++; //相当于从左边收缩该区间
}
}
return minvalue == INT_MAX ? "" : s.substr(minLeft, minvalue+1); //注意中可能找不到t
}
};