你好,我是本文作者南一。如果有发现错误或者可完善的地方,恳请斧正,万分感谢!!
先尝试暴力解...
将 p 字符串每一个字符用 map 保存,并记录个数;遍历 s 字符串一个个匹配,直到有符合的,即所有字符用完的字符串就 push 到结果集。
思路正确,但是超时了...
var findAnagrams = function (s, p) {
const map = {};
for (let i = 0; i < p.length; i++) {
if (map[p[i]]) {
map[p[i]]++;
} else {
map[p[i]] = 1;
}
}
const result = [];
for (let i = 0; i < s.length; i++) {
let j = i,
cloneMap = { ...map };
while (j < s.length && cloneMap[s[j]]) {
cloneMap[s[j]]--;
j++;
}
if (j - i === p.length) {
result.push(i);
}
}
return result;
};
再试试双指针滑动窗口,顺利通过!!!
var findAnagrams = function (s, p) {
// 第一步 收集 p 所有字符存在 map中
const map = {};
for (let i = 0; i < p.length; i++) {
if (map[p[i]]) {
map[p[i]]++;
} else {
map[p[i]] = 1;
}
}
const result = [];
// 第二步 双指针滑动窗口;核心思路:使 [i, j] 区间内就是要找的异位词
let i = 0,
j = i;
while (i <= j && j <= s.length) {
if (map[s[j]]) {
map[s[j]]--;
j++;
} else {
// 当 j 指针所指字符 不在 map 中时,存在两种情况 1. s[i] 不在p中; 2. s[i] 在p中 但是个数用完了
// 1. 长度=== p的长度,那么 [i, j] 区间内就是要找的异位词
if (j - i === p.length) {
result.push(i);
}
// 2. j和i相等,此时没消耗过map中的字符,那么只能是 s[i] 不在p中。
// 此时需要 i 和 j 都往前走一步,因为只要区间[i, j] 包含了当前 s[i] 那他就永远不可能是异位词
if (j === i) {
j++;
} else {
// 恢复 s[i] 在map中的字符个数。
// 为什么是在 j !== i 的逻辑中恢复呢?因为不能把不在 p 中的 s[i] 给记录下来。
map[s[i]]++;
}
i++;
}
}
return result;
};