【JS每日一算法】🟥70.最小覆盖子串(滑动窗口)

305 阅读1分钟

给你一个字符串s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

提示:

  • m == s.length
  • n == t.length
  • 1 <= m, n <= 105
  • s 和 t 由英文字母组成

示例:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A''B''C'

题解:

更多JS版本题解点击链接关注该仓库👀

/**
 * @description: 滑动窗口   TC:O(n)  SC:O(n)
 * @author: JunLiangWang
 * @param {*} s 给定字符串
 * @param {*} t 匹配字符串
 * @return {*}
 */
function slideWindow(s, t) {
    /**
     * 该方案使用滑动窗体的方式,首先遍历匹配字符串t,使用hashMap记录
     * 匹配字符串t中的所有单词的数量,然后使用遍历wordCount记录匹配字
     * 符串t中不重复的单词数量。
     * 
     * 然后定义左右两指针初始化指向首个元素,右指针不断向右移动,直至
     * 找到了匹配字符串t中的所有字符(如果遍历完仍无直接返回空即可)
     * 并记录该字符串(长度最小),然后将左指针也向右移动,直至无法满足
     * 找到匹配字符串t中的所有字符时,此时又移动右指针,如此往复直到右
     * 指针超过了字符串s的长度
     */

    // 记录字符串t中所有单词的数量
    let recordMap = new Map(),
        // 记录字符串t中不重复的单词数量
        wordCount = 0;
    // 遍历字符串t,记录数据
    for (let i = 0; i < t.length; i++) {
        let val = recordMap.get(t[i])
        if (val) {
            recordMap.set(t[i], val + 1);
        }
        else {
            recordMap.set(t[i], 1);
            wordCount++;
        }
    }
    // 定义左指针指向首个元素
    let left = 0,
    // 定义右指针指向首个元素
        right = 0,
    // 记录最小的字符串
        result = '',
    // 记录临时满足条件的字符串
        tempResult = '';
    // 遍历字符串s,直至右指针超出字符串长度
    while (right <= s.length) {
        // 如果单词数量大于0,证明未找到t中的所有字符,
        // 此时不断移动右指针,直到找到所有t中字符
        if (wordCount > 0) {
            // 向临时满足条件的字符串追加字符
            tempResult += s[right];
            // 查看是否添加了t中的字符,如果是则需要做相应的记录
            let temp = recordMap.get(s[right])
            if (temp != undefined) {
                recordMap.set(s[right], temp - 1);
                if (temp - 1 == 0) wordCount--;
            }
            // 移动右指针
            right++;
        }
        // 反之,证明已找到t中的所有字符,这时候我们需要
        // 记录满足条件的最小子串,并且不断向右移动左指针
        // ,缩小满足条件的子串长度,当我们删除了t中的字符
        // ,子串无法满足找到字符串t中的所有字符,此时再去
        // 移动右指针    
        else {
            // 记录满足条件的最小子串
            if (result == '' || tempResult.length < result.length)
                result = tempResult  
            // 查看是否删除了t中的字符,如果是则需要做相应的记录
            let temp = recordMap.get(s[left])
            if (temp != undefined) {
                recordMap.set(s[left], temp + 1)
                if (temp == 0) wordCount++;
            }
            tempResult = tempResult.slice(1)
            // 移动左指针
            left++;
        }
    }
    // 返回结果
    return result;
}

来源:力扣(LeetCode)