力扣438(Java)-找到字符串中所有字母异位词(中等)

发布时间 2023-05-08 13:44:58作者: 我不想一直当菜鸟

题目:

给定两个字符串 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 仅包含小写字母

来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

滑动窗口+哈希表(数组)

  • 因为给定的字符串都是由小写字母组成,故可以使用数组形式的哈希表先统计出字符串p中各字符出现的次数;
  • 维护一个窗口,窗口的长度始终与p的长度一致,定义两个指针left代表窗口的起始位置,right代表窗口的结束位置;
  • 判断窗口中的字符数量和 p 中出现的字符数量是否一致,如果一致就添加窗口的起始位置到结果中,否则,就移动窗口位置,将结束位置右移,起始位置也右移并删除掉起始位置对应字符的数量。

代码:

 1 class Solution {
 2     public List<Integer> findAnagrams(String s, String p) {
 3         int m = s.length(), n = p.length();
 4         //定义一个数组统计p中字符出现的次数
 5         int[] count = new int[26];
 6         for(int i = 0; i < p.length(); i++){
 7             count[p.charAt(i) - 'a']++;
 8         }
 9         //定义双指针为窗口的起始和结束位置
10         int left = 0, right = 0;
11         int[] window = new int[26];
12         //定义一个字符串用于返回结果
13         List<Integer> ans = new ArrayList<>();
14         while (right < m){
15             window[s.charAt(right) - 'a']++;
16             //控制窗口大小等于p的长度
17             if (right - left + 1 == n){
18                 if (Arrays.equals(window, count)){
19                     ans.add(left);
20                 }
21                 //将窗口左指针对应的字符数量减减
22                 window[s.charAt(left) - 'a']--;
23                 //左指针向右移动
24                 left++;
25             }
26             right++;
27         }
28         return ans;
29     }
30 }