1.设置两个字符哈希数组,map_s,代表当前处理的窗口区间中的字符数量,map_t,代表子串t的字符数量
2.设置两个指针(begin, i)指向字符串第一个字符
3.i指针向后逐个扫描字符串中的字符,在这过程中,循环检查begin指针是否可以向前移动:
如果当前begin指向的字符,在t中没有出现,直接向前移动begin,
如果当前begin指向的字符,在t中出现了,但是当前区间窗口中的该字符数量足够,则向前移动begin,并更新map_s
否则,不能移动begin,跳出检查
4.指针i每向前扫描一个字符,即检查一下是否可以更新最终结果
在整个过程中,begin,i维护一个窗口,窗口线性向前滑动,整体时间复杂度O(N)
class Solution {
public:
//检查包含函数,检查s是否包含t子串字符
bool is_window(int map_s[],int map_t[],vector<int>& vec_t)//利用vec_t遍历t中出现的字符
{
for(int i = 0;i<vec_t.size();++i)
{
if(map_s[vec_t[i]] < map_t[vec_t[i]])
return false;
}
return true;
}
string minWindow(string s, string t) {
int map_s[128] = {0};
int map_t[128] = {0};
vector<int> vec_t;
for(int i =0;i< t.length();i++)
map_t[t[i]]++;
for(int i =0;i<128;++i)
{
if(map_t[i] > 0)
vec_t.push_back(i);
}
int begin = 0;//窗口的起点
string res;
for(int i =0;i<s.length();++i)
{
map_s[s[i]]++;
//检查现在的Begin能不能向前移动
while(begin < i)
{
char begin_ch = s[begin];
if(map_t[begin_ch] == 0)//如果当前begin的字符不存在与子串中,就可以前移
{
begin++;
}
else if(map_s[begin_ch] > map_t[begin_ch])//如果当前窗口中的begin对应的字符数量够多,也可以前移
{
map_s[begin_ch]--;
begin++;
}
else//否则不能前移begin,跳出
{
break;
}
}
//检查当前的窗口是不是包含子串t的
if(is_window(map_s,map_t,vec_t))
{
int new_len = i - begin + 1;//现在这个窗口的长度
if(res == "" || new_len < res.length())
res = s.substr(begin,new_len);//更新结果字符串
}
}
return res;
}
};