给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T
所有字符的最小子串。示例:
输入:S = “ADOBECODEBANC”, T = “ABC” 输出:“BANC”
提示:
如果 S 中不存这样的子串,则返回空字符串 “”。 如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
该题利用滑动窗口与哈希表方法。首先哈希表要记录t串中的字符出现数量,还要记录窗口中出现t字符的数量,窗口必须满足t中的字符在窗口中的数量相同。
窗口的建立:头指针begin 尾指针就是循环中的i。
头指针后移的情况:
1.当前指向的字符没有在t中出现
2.当前指向的字符 在窗口中的数量 大于了t中出现的数量
然后要检查窗口中的出现t中的字符数量是否相同,如果相同并且长度小于之前的临时字符串就更新临时字符串
class Solution {
public:
bool isWindowOk(int maps[],int mapt[],vector<int>&str)
{//判断窗口里出现在t中的字符 与t中字符数量是否相等
for(int i=0;i<str.size();i++)
{
if(maps[str[i]]<mapt[str[i]])//如果在窗口中的字符数量小于t串中的字符数量
{
return false;
}
}
return true;
}
string minWindow(string s, string t) {
int map_s[128]={0};//存储当前滑动窗口中出现字符的数量
int map_t[128]={0}; //存储t串中字符数量
vector<int>str;//存储t串出现了哪些字符
for(int i=0;i<t.size();i++)
{
map_t[t[i]]++;//记录出现在t中的字符数量
}
for(int i=0;i<128;i++)
{
if(map_t[i]>0)//如果该字符在t串中出现
{
str.push_back(i);//存储出现该字符的位置
}
}
int begin=0;//头指针
string res="";
for(int i=0;i<s.size();i++)
{
map_s[s[i]]++;//将尾指针指向放入哈希表
while(begin<i)
{
char ch=s[begin];//当前头指针指向的字符
if(map_t[ch]==0)//如果头指针的字符没有在t串中出现 则直接跳跃
{
begin++;
}
else if(map_s[ch]>map_t[ch])//如果在窗口出现的字符数量大于在t串中出现的数量 就后移
{
map_s[ch]--;
begin++;
}
else
{
break;//除了两种后移情况 就跳出循环
}
}
if(isWindowOk(map_s,map_t,str))//如果窗口中的字符数量都够了
{
int resSize=i-begin+1;//新窗口的长度
if(res==""||res.size()>resSize)//如果字符串为空或者字符串长度大于新窗口长度
{
res=s.substr(begin,resSize);//更新字符串
}
}
}
return res;
}
};