LeetCode-438. 找到字符串中所有字母异位词

题目来源

438. 找到字符串中所有字母异位词

题目详情

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

题解分析

解法一:移动窗口

  1. 一开始看到本题,其实是有些害怕的,因为按照题目的描述,这既涉及到全排列,又涉及到字符串子串的查找,所以一开始是懵的。
  2. 但是,仔细一想,其实可以发现,这里对于字符串的全排列就是两个子串,它们的每个相同字符的数量也相同,即可认定为是原串的全排列子串。
  3. 此外,对于子串的查找,则可以使用移动窗口的方法,设置一个大小为sn-pn的窗口,每次往前移动一个窗口。在移动的过程中,维护一个数组,里面保存了窗口里面的字符串的每个字符的数量,如果移动后的子串的字符数量数组与原数组一样,则是符合题意的子串,并记录下位置。
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sn = s.length();
        int pn = p.length();
        if(sn < pn){
            return List.of();
        }
        int[] scnt = new int[26];
        int[] pcnt = new int[26];
        for(int i=0; i<pn; i++){
            scnt[s.charAt(i) - 'a']++;
            pcnt[p.charAt(i) - 'a']++;
        }
        List<Integer> res = new ArrayList<>();
        if(Arrays.equals(scnt, pcnt)){
            res.add(0);
        }
        // 滑动窗口
        for(int i=0; i< sn-pn; i++){
            scnt[s.charAt(i) - 'a']--;
            scnt[s.charAt(i + pn) - 'a']++;
            if(Arrays.equals(scnt, pcnt)){
                res.add(i+1);// 这里是i+1
            }
        }
        return res;
    }
}
posted @ 2022-01-03 23:15  Garrett_Wale  阅读(143)  评论(0编辑  收藏  举报