题目

类型:滑动窗口
image.png

解题思路

1、异位词的长度一定与字符串 p 的长度相同,所以我们可以在字符串 s 中构造一个长度为与字符串 p 的长度相同的滑动窗口
2、统计滑动窗口和字符串 p 中每种字母数量的差;并引入变量 differ 来记录当前窗口与字符串 p 中数量不同的字母的个数,并在滑动窗口的过程中维护它。
3、在判断滑动窗口中每种字母的数量与字符串 p中每种字母的数量是否相同时,只需要判断differ 是否为零即可。
4、当字符串 s 的长度小于字符串 p 的长度时,字符串 s 中一定不存在字符串 p 的异位词。但是因为字符串 s 中无法构造长度与字符串 p 的长度相同的窗口,所以这种情况需要单独处理。

代码

  1. class Solution {
  2. public List<Integer> findAnagrams(String s, String p) {
  3. List<Integer> ans = new ArrayList<>();
  4. int n = s.length(), m = p.length();
  5. int[] cnt = new int[26];
  6. //遍历目标字符串,统计每个字母的个数,使用cnt数组存放
  7. for (int i = 0; i < m; i++) {
  8. cnt[p.charAt(i) - 'a']++;
  9. }
  10. int a = 0;
  11. //用a统计目标字符串不同的字母数量
  12. for (int i = 0; i < 26; i++) {
  13. if (cnt[i] != 0) {
  14. a++;
  15. }
  16. }
  17. for (int l = 0, r = 0, b = 0; r < n; r++) {
  18. // 往窗口增加字符,进行词频的抵消操作,如果抵消后词频为 0,说明有一个新的字符词频与 p 完全相等
  19. if (--cnt[s.charAt(r) - 'a'] == 0) {
  20. b++;
  21. }
  22. // 若窗口长度超过规定,将窗口左端点右移,执行词频恢复操作,如果恢复后词频为 1(恢复前为 0),说明少了一个词频与 p 完全性相等的字符
  23. if (r - l + 1 > m && ++cnt[s.charAt(l++) - 'a'] == 1){
  24. b--;
  25. }
  26. if (b == a) {
  27. ans.add(l);
  28. }
  29. }
  30. return ans;
  31. }
  32. }