题目来源:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
大致题意:
给定两个字符串 s 和 p,查找字符串 s 是否有子串的所有组成字母和 p 完全一致。
返回所有符合该条件的的 s 的子串的开始索引的集合
思路
找给定长度的子串 == 滑动窗口
滑动窗口
- 使用两个大小为 26 的数组 pCount 和 sCount 分别存下 p 和 s 的长度为 p.length() 的子串的不同字母对应的数量
- 初始时,先统计 pCount
- 遍历字符串 s,将当前位置对应的字母数量加 1,若当前遍历的次数大于等于 p.length() 后,判断两个数组是否相等,若相等将 当前位置减去 - p.length() + 1 的索引放入答案集合。接下来,在 sCount 中将 当前位置减去 - p.length() + 1 位置对应的字母数量减 1
代码:
public List<Integer> findAnagrams(String s, String p) {
List<Integer> ans = new ArrayList<>();
int n = p.length();
int[] pCount = new int[26];
int[] sCount = new int[26];
// 先统计 p 的不同字母的数量
for (int i = 0; i < n; i++) {
pCount[p.charAt(i) - 'a']++;
}
// 统计 s 的大小为 pLen 的子串中不同字母的数量
for (int i = 0; i < s.length(); i++) {
// 滑动窗口,当前位置对应的字母数量++
sCount[s.charAt(i) - 'a']++;
// 窗口已经形成
if (i >= n - 1) {
// 判断
if (Arrays.equals(pCount, sCount)) {
// 存下窗口的开始索引
ans.add(i - n + 1);
}
// 滑动窗口,当前的首字母需要移除
sCount[s.charAt(i - n + 1) - 'a']--;
}
}
return ans;
}