题目:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
具体实现
用 strT[] 当作哈希表,统计字符串 t 中各元素的哈希值,用 lenT 统计还未找到的字符串 t 中字母的个数。
右指针 right 从字符串 s 头移动到字符串 s 尾: s 中每个字母的对应的哈希表 -1,若字符串 s 有字符串 t 的字母(即哈希值被减一之前 >0),则 lenT-- ;
如果出现匹配的子串(即 lenT == 0 ,此时所有 t 中字母对应的哈希值都 ==0,非 t 字母对应的哈希值 <0):更新最小匹配子串的起点 min 和终点 max ,然后 left++ 。不过在 left++ 之前要先更新窗口数据,即先将left的字母的哈希值 +1,如果加一后其值 >0,则这个字母在 t 中存在,所以要 lenT++ 。
当if (max != INT32_MAX) ,找到了最小匹配字串;若未找到最小匹配子串,返回""。
char * minWindow(char * s, char * t){
int strT[58] = {0};//定义哈希表
int lenS = strlen(s);
int lenT = strlen(t);
for(int i = 0; i < lenT; i++)//初始化哈希表
{
strT[t[i] - 'A']++;
}
int min = 0, max = INT_MAX;
for(int i = 0, j = 0; i < lenS; i++)//遍历字符串
{
if(strT[s[i] - 'A']-- > 0)//出现相同元素
{
lenT--;
}
while(lenT == 0)//维护滑动窗口
{
if((i-j) < (max - min))//记录字符串出现位置
{
min = j;
max = i;
}
if(++strT[s[j] - 'A'] > 0)
{
lenT++;
}
j++;
}
}
if(max == INT_MAX)
return "";
char * res = malloc(sizeof(char) * (max - min + 2));//保存字符串并输出
int i = 0;
while(min <= max)
{
res[i++] = s[min++];
}
res[i] = '\0';
return res;
}