76. 最小覆盖子串

·  阅读 72

题目描述

给你一个字符串 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;
}
复制代码
分类:
后端
标签: