# 滑动窗口
# 03. 无重复字符的最长子串 (opens new window)
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
1
2
3
2
3
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
1
2
3
2
3
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
1
2
3
4
2
3
4
示例 4:
输入: s = ""
输出: 0
1
2
2
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
题解
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
const set = new Set();
let countMax = 0;
let [l, r] = [0, 0];
if(s.length<=1) return s.length
while (r <= s.length - 1) {
if (set.has(s[r])) {
// 注意这里是删除s[l] 因为窗口向右滑动 删除开头的字母
set.delete(s[l]);
l++;
} else {
countMax = Math.max(countMax, r - l + 1);
set.add(s[r])
r++
}
}
return countMax;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 76. 最小覆盖子串 (opens new window)
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
1
2
3
2
3
示例 2:
输入:s = "aa", t = "aa"
输出:"aa"
解释:整个字符串 s 是最小覆盖子串。
1
2
3
2
3
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
1
2
3
4
2
3
4
题解
/**
* @param {string} s
* @param {string} t
* @return {string}
*/
var minWindow = function (s, t) {
// 思路
// 一直r++到能覆盖t为止 记录长度
// 然后l++ 如果还能覆盖 记录长度 如果不够 则 停止, 继续重复上面一步
let res = "";
// 长度先给一个最大值 不然后面比较长度的时候都不会比他小
let resLen = Number.MAX_SAFE_INTEGER;
let l = 0,
r = 0;
// 比如abbc charCount最大就是3 b两个都减完了 这个数-1 当他为0的时候 说明当前是一个备选目标答案
let charCount = new Set(t.split("")).size;
// key:char value初始是char在t的个数, 等于0的时候,说明这个char够了, 可以给count+1
let map = new Map();
for (char of t) {
map.set(char, (map.get(char) || 0) + 1);
}
// l++的过程
while (r <= s.length - 1) {
// 是目标char
if (t.includes(s[r])) {
// 处理map和count
map.set(s[r], map.get(s[r]) - 1);
// 这时候s[r]字母 齐了 (可能会有负数, 所以等于0的时候就要记录一次)
if (map.get(s[r]) === 0) {
// charCount先-1 再判断子串字母是否都齐了
if (--charCount === 0) {
if (r - l + 1 < resLen) {
resLen = r - l + 1;
res = s.slice(l, r + 1);
}
// 齐了的时候开始l++
while (charCount === 0) {
if (r - l + 1 < resLen) {
resLen = r - l + 1;
res = s.slice(l, r + 1);
}
if (t.includes(s[l])) {
// 如果当前是0的话, 代表马上就不够了
if (map.get(s[l]) === 0) {
charCount++;
}
map.set(s[l], map.get(s[l]) + 1);
}
l++;
}
}
}
}
r++;
}
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
63
64
65
66
67
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
63
64
65
66
67