「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。
1.题目
盛最多水的容器
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab" 输出: [0,1,2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
提示:
1 <= s.length, p.length <= 3 * 104 s 和 p 仅包含小写字母
思路
具体的,我们可以先创建一个大小为 2626 的数组 c2c2 来统计字符串 p 的词频,另外一个同等大小的数组 c1c1 用来统计「滑动窗口」内的 s 的子串词频。
当两个数组所统计词频相等,说明找到了一个异位组,将窗口的左端点加入答案。
时间复杂度: 令 s 和 p 的长度分别为 nn 和 mm,C = 26C=26 为字符集大小。 统计 p 词频(构建 c2c2 数组)的复杂度为 O(m)O(m);使用双指针检查 s 串的复杂度为 O(C * n)O(C∗n)。 整体复杂度为 O(C*n + m)O(C∗n+m) 空间复杂度:O(C)O(C)
代码
var findAnagrams = function(s, p) {
let tar = new Map();
function findRes(map) {
let values = map.values();
for (let v of values) {
if (v !== 0) return false;
}
return true;
}
for (let i of p) {
if (tar.has(i)) tar.set(i, tar.get(i)+1);
else tar.set(i, 1);
}
let l = 0; r = 0;
let res = [];
while (r < s.length+1) {
if (r < p.length) {
if (tar.has(s[r])) tar.set(s[r], tar.get(s[r])-1);
r++;
} else {
if (findRes(tar)) res.push(l);
if (tar.has(s[l])) tar.set(s[l], tar.get(s[l])+1);
if (r < s.length && tar.has(s[r])) tar.set(s[r], tar.get(s[r])-1);
l++; r++;
}
}
return res;
};