438\. 找到字符串中所有字母异位词
# 438. 找到字符串中所有字母异位词 (opens new window)
# Description
Difficulty: 中等
Related Topics: 哈希表 (opens new window), 字符串 (opens new window), 滑动窗口 (opens new window)
给定两个字符串 s
和 p
,找到 s
中所有 p
的 **异位词 **的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
1
2
3
4
5
2
3
4
5
** 示例 2:**
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
1
2
3
4
5
6
2
3
4
5
6
提示:
- 1 <= s.length, p.length <= 3 * 104
s
和p
仅包含小写字母
# Solution
Language: JavaScript
/**
* @param {string} s
* @param {string} p
* @return {number[]}
*/
var findAnagrams = function (s, p) {
const pLen = p.length
const res = [] // 返回值
const map = new Map() // 存储 p 的字符
for (let item of p) {
map.set(item, map.get(item) ? map.get(item) + 1 : 1)
}
// 存储窗口里的字符情况
const window = new Map()
let valid = 0 // 有效字符个数
for (let i = 0; i < s.length; i++) {
const right = s[i]
// 向右扩展
window.set(right, window.get(right) ? window.get(right) + 1 : 1)
// 扩展的节点值是否满足有效字符
if (window.get(right) === map.get(right)) {
valid++
}
if (i >= pLen) {
// 移动窗口 -- 超出之后,收缩回来, 这是 pLen 长度的固定窗口
const left = s[i - pLen]
// 原本是匹配的,现在移出去了,肯定就不匹配了
if (window.get(left) === map.get(left)) {
valid--
}
window.set(left, window.get(left) - 1)
}
// 如果有效字符数量和存储 p 的map 的数量一致,则当前窗口的首字符保存起来
if (valid === map.size) {
res.push(i - pLen+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
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