438. 找到字符串中所有字母异位词
题目: 给定两个字符串 s 和 p,找到 s中所有 p的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

思路: 采用 滑动窗口 + 字符计数。
核心思想:
异位词要求:窗口内每个字符出现次数和 p 完全相同。
具体过程:
-
统计字符串
p中每个字符出现次数。 -
使用长度为
p.length()的窗口遍历s:-
右指针移动,新字符加入窗口。
-
当窗口长度达到
p.length()时:-
比较窗口中字符次数和
p是否一致。 -
如果一致,记录窗口左端点。
-
-
窗口向右移动,移除左端字符。
-
时间复杂度: O(26n)
空间复杂度: O(1)
class Solution {
public List<Integer> findAnagrams(String s, String p) {
// 统计 p 的每种字母的出现次数
int[] cntP = new int[26];
for (char c : p.toCharArray()) {
cntP[c - 'a']++; // 统计 p 的字母
}
List<Integer> ans = new ArrayList<>();
int[] cntS = new int[26]; // 统计 s 的长为 p.length() 的子串 t 的每种字母的出现次数
for (int right = 0; right < s.length(); right++) {
cntS[s.charAt(right) - 'a']++; // 右端点字母进入窗口
int left = right - p.length() + 1;
if (left < 0) { // 窗口长度不足 p.length()
continue;
}
if (Arrays.equals(cntS, cntP)) { // t 和 p 的每种字母的出现次数都相同
ans.add(left); // t 左端点下标加入答案
}
cntS[s.charAt(left) - 'a']--; // 左端点字母离开窗口
}
return ans;
}
}
可参考思路讲解 史上最燃算法刷题!滑动窗口的逆袭!Leetcode 438. 找到字符串中所有字母异位词_哔哩哔哩_bilibili