Skip to main content

找到字符串中所有字母异位词

题目

给定一个字符串 s 和一个非空字符串 p, 找到 s 中所有是 p 的字母异位词的子串, 返回这些子串的起始索引. 字符串只包含小写英文字母, 并且字符串 s 和 p 的长度都不超过 20100.

说明:

字母异位词指字母相同, 但排列不同的字符串. 不考虑答案输出的顺序.

示例
输入: s = "cbaebabacd" p = "abc"

输出: [0, 6]

解释:

起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词.
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词.
输入: s = "abab" p = "ab"

输出: [0, 1, 2]

解释:

起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词.
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词.
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词.

题解

具体题解看 567. 字符串的排列 这道题即可.

/**
* @param {string} s
* @param {string} p
* @return {number[]}
*/
var findAnagrams = function (s, p) {
const result = []

const needMap = new Map()
for (const ch of p) {
needMap.set(ch, needMap.has(ch) ? needMap.get(ch) + 1 : 1)
}

const windowMap = new Map()
let metCount = 0
let start = 0
let end = 0

while (end < s.length) {
const endCh = s[end++]
if (needMap.has(endCh)) {
windowMap.set(endCh, windowMap.has(endCh) ? windowMap.get(endCh) + 1 : 1)
if (windowMap.get(endCh) === needMap.get(endCh)) {
metCount++
}
}

// 只有窗口长度等于了 p 的长度, 才有可能匹配到异位词, 此时就到了收缩窗口的时候
while (end - start === p.length) {
if (metCount === needMap.size) {
result.push(start)
}

const startCh = s[start++]
if (needMap.has(startCh)) {
if (windowMap.get(startCh) === needMap.get(startCh)) {
metCount--
}
windowMap.set(startCh, windowMap.get(startCh) - 1)
}
}
}

return result
}