题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/mi…
实现
char *minWindow(char * s, char * t)
{
if (strlen(s) < strlen(t)) {
return "";
}
if (strlen(t) == 0 || t == NULL) {
return NULL;
}
int hash[128] = {0}; // 各元素的个数
bool flag[128] = {false};
int l = 0;
int r = 0;
int minL = 0; // 最小匹配的起点
int minR = strlen(s) + 1; // 最小匹配的终点
int num = 0; // 目前已经找到的t中字符的数目
for (int i = 0; i < strlen(t); i++) { // 统计 t 中的各元素 hash 值
flag[t[i]] = true;
hash[t[i]]++;
}
// 滑动窗口
for (r = 0; r < strlen(s); r++) {
if (flag[s[r]]) { // s[r]在t中
if (--hash[s[r]] >= 0) { // 在s中找到一个t中的元素
num++;
}
}
while (num == strlen(t)) { // 全部找到,left试着右移
// 判断该范围是否比现有范围小,如果小,替换
if (r - l < minR - minL) {
minL = l;
minR = r;
}
// 判断是否可以右移,如果s[l]是t中元素,并且在范围中还有多余的s[l],那么说明l可以右移,否则,num--,退出while循环
if (flag[s[l]] && (++hash[s[l]]) > 0) {
num--;
}
l++;
}
}
if (minR == strlen(s) + 1) {
return "";
}
int idx = 0;
char *res = (char*)malloc(sizeof(char) * (minR - minL + 2));
memset(res, 0, minR - minL + 2);
for (int i = minL; i <= minR; i++) {
res[idx++] = s[i];
}
return res;
}