76\. 最小覆盖子串

# 76. 最小覆盖子串 (opens new window)

# Description

Difficulty: 困难

Related Topics: 哈希表 (opens new window), 字符串 (opens new window), 滑动窗口 (opens new window)

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

注意:

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

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

# Solution

Language: JavaScript

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 * 子串强调了[连续性]
 * T中可能包含重复字符
 * 1.暴力解法
 * 枚举输入字符串S的所有长度大于等于T的子串
 * 逐个判断这些子串中,哪些子串覆盖了字符串T的所有字符;
 * 在枚举的过程中,记录符合条件的,长度最短的那个子串。
 * 
 * 如何判断S的子串包含了T中的所有字符?
 * 参考做法:分别统计S的子串和T中每个字符出现的次数,然后逐个比对。
 * 字符频数数组
 */
// 滑动窗口:
// 1.什么时候移动右边界:当前窗口内的字符串,没有覆盖到子串,右边界越出数组边界,程序可以退出
// 2.什么时候移动左边界:当前窗口的字符串已经覆盖到子串,需要把窗口尽可能缩小,当继续缩小后不满足题意得时刻,就是满足的一个答案
// 3. 多个答案需要比较字符串长度
// 4. 因此需要使用unordered_map记录字符个数
// 5. helper辅助函数,用来比较窗口内是否完全覆盖子串,当窗口某个字符频次小于子串对应字符,false

// 1.创建左指针,右指针
// 2.将输入t的所有字符存入,map中
// 3.建立循环,直到右指针到s字符串长度结束
// 4.逐位移动右指针
// 5.如果need中有当前右指针的字符,need中当前右指针字符对应的value - 1
// 6.如果当前右指针字符对应的value === 0 needType -= 1
// 7.当needType === 0时候说明已经找到符合要求的子串开始处理左指针

var minWindow = function(s, t) {
 let l = 0
 let r = 0
 const need = new Map()
 for(let c of t) {
  need.set(c, need.has(c) ? need.get(c) + 1 : 1)
 }

 let needType = need.size
 let res = ''
 while (r < s.length) {
  let c = s[r]
  if (need.has(c)) {
   need.set(c, need.get(c) - 1)
   if (need.get(c) === 0) needType -= 1
  }

  while (needType === 0) {
   const newRes = s.substring(l, r + 1)
   if (!res || newRes.length < res.length) res = newRes

   const c2 = s[l]
   if (need.has(c2)) {
    need.set(c2, need.get(c2) + 1)
    if (need.get(c2) === 1) needType += 1
   }
   l += 1
  }
  r += 1
 }
 return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
上次更新: 2022/7/31 下午1:04:14