Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

76. 最小覆盖子串 #26

Open
webVueBlog opened this issue Sep 12, 2022 · 0 comments
Open

76. 最小覆盖子串 #26

webVueBlog opened this issue Sep 12, 2022 · 0 comments

Comments

@webVueBlog
Copy link
Owner

webVueBlog commented Sep 12, 2022

76. 最小覆盖子串

Description

Difficulty: 困难

Related Topics: 哈希表, 字符串, 滑动窗口

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

注意:

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

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

示例 2:

输入:s = "a", t = "a"
输出:"a"

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

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

**进阶:**你能设计一个在 o(n) 时间内解决此问题的算法吗?

Solution

Language: JavaScript

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
// 将需要匹配的字符放入字典表,存储结构为需要匹配的字符,以及字符出现的次数:[字符,次数]
// 利用双指针维护一个滑动窗口,不断移动右指针
// 判断右指针的字符是否与字典表中的匹配
// 是:将字典表中的次数-1,直到为0 (创建一个needType)记录需要匹配的字符数量,初始长度为Map的size,当对应的字符次数为0时,就减1
// 否:继续移动右指针
// 当needType的值为0时,就证明在当前窗口所有字符都匹配成功了
// 1.移动左指针,缩小滑动窗口的大小
// 2.移动过程中判断左指针指向的值是否为字典中值,如果是就证明匹配的值少了一个,这个需要更新Map中的次数,以及needType的数量
// 3.记录每次窗口中的字符,找到最小的返回
var minWindow = function(s, t) {
    // 创建左指针
    let l = 0
    // 创建右指针
    let r = 0
    // 最后需要返回的最小长度子串
    let res = ''
    // 创建字典表
    const m = new Map()
    // 遍历需要匹配的字符
    for (let i = 0; i < t.length; i++) {
        const c = t[i]
        // 放入字典表
        m.set(c, m.has(c) ? m.get(c) + 1 : 1)
    }
    // 创建记录需要匹配的字符种类
    let needType = m.size
    // 遍历字符串
    while (r < s.length) {
        // 获取当前字符
        const c = s[r]
        // 如果是需要匹配的字符
        if (m.has(c)) {
            // 更新字典表中的次数-1
            m.set(c, m.get(c) - 1)
            // 如果次数为0,证明这个字符种类在当前窗口已经集齐了,needType-1
            if (m.get(c) === 0) needType -= 1
        }
        // 当needType为0,证明所有需要匹配的字符串都已经在当前滑动窗口中
        while (needType === 0) {
            const c2 = s[l]
            // 记录当前滑动窗口的字符
            let newRes = s.slice(l, r + 1)
            // 当新的窗口中字符长度小于上次的字符长度时,更新结果
            // !res 是在结构值为空的时候需要更新一下第一次匹配的值
            if (!res || newRes.length < res.length) res = newRes
            // 如果左指针移动过程中出现,字典中的值证明需要匹配的字符已经脱离了当前窗口
            if (m.has(c2)) {
                // 更新表中需要出现的次数
                m.set(c2, m.get(c2) + 1)
                // 更新needType
                if (m.get(c2) === 1) needType += 1
            }
            // 移动左指针
            l++
        }
        // 移动右指针
        r++
    }
    // 返回结果值
    return res
}
@webVueBlog webVueBlog changed the title 72. 编辑距离 76. 最小覆盖子串 Sep 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant