题目链接:https://leetcode-cn.com/problems/minimum-window-substring/
题意:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
方法:哈希表+滑动窗口
class Solution {
public:
string minWindow(string s, string t) {
string ret="";//返回字符串
unordered_map<char,int> mp;//哈希表
int minL=s.size();//最短的长度初始化为s的size
int left=0,right=0,diff=0;//滑动窗口左侧坐标,滑动窗口右侧坐标,字符总数
int pos = 0;//最优的左侧位置
//存哈希表,记录下t中的字符总数
for(auto &ch:t)
{
mp[ch]++;
diff++;
}
//窗口滑动
while(right<s.size())//滑动窗口右侧没到终点时就不停
{
if(mp.find(s[right])!=mp.end())//如果当前字符s[right]在哈希表中找到了
{
mp[s[right]]--;//key值为s[right]对应的value值减1
if(mp[s[right]]>=0)//如果减完以后还是正的,字符数减1
diff--;
}
while(diff==0)//假如字符数为0,就说明都找到了,滑动窗口左侧开始滑动
{
if(minL>right-left)//更新一下最短的长度
{
minL=right-left;
pos = left;
}
if(mp.find(s[left])!=mp.end())//如果这个字符在哈希表中
{
mp[s[left]]++;//key值为s[left]对应的value值加1
if(mp[s[left]]>0)//如果加完以后对应的value值大于0,字符数就加1
diff++;
}
left++;//滑动
}
right++;//滑动
}
if(pos==0&&minL==s.size()) return ret;
ret=s.substr(pos,minL+1);
return ret;
}
};
代码优化:
class Solution {
public:
string minWindow(string s, string t) {
int minV = -100000;//定义最小值
int len = s.size();//s字符串的长度
int right=0,left=0,pos=0,minL=len,diff=t.size();//滑动窗口右侧坐标,滑动窗口左侧坐标,起始位置坐标,最短长度,不同的字符数量
vector<int> mp(127,minV);//哈希表,<字符,出现次数>
for(auto& ch:t)
{
if(mp[ch]==minV)//第一次出现,先更新初始值
mp[ch]=0;
mp[ch]++;//更新哈希表
}
while(right<len)//限定滑动窗口移动的极限
{
if(mp[s[right]]!=minV)//对应的字符在t中
{
mp[s[right]]--;//更新哈希表
if(mp[s[right]]>=0)//当对应的value值小于0时不再自减
diff--;//不同的字符数量减1
}
while(diff==0)//有差异的字符数目为0
{
if(minL>right-left)//更新最短长度和起始位置
{
minL = right-left;
pos = left;
}
if(mp[s[left]]!=minV)//对应的字符在t中
{
mp[s[left]]++;//更新哈希表
if(mp[s[left]]>0)
diff++;//不同的字符数量减1
}
left++;//滑动窗口左侧坐标右移
}
right++;//滑动窗口右侧坐标右移
}
if(pos==0&&minL==len) return "";//如果没找到,返回空值
return s.substr(pos,minL+1);//否则返回这个子串
}
};