当前位置:   article > 正文

LeetCode438:找到字符串中所有字母异位词_438. 找到字符串中所有字母异位词 java

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

要求

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
在这里插入图片描述

思路

方法一:滑动窗口 + 双指针
用双指针来表示滑动窗口的两侧边界,当滑动窗口的长度等于p的长度时,表示找到一个异位词

定义滑动窗口的左右两个指针left,right;表示滑动窗口在字符串s中的索引,
right一步一步向右走遍历s字符串
right当前遍历到的字符加入s_cnt后不满足p_cnt的字符数量要求,将滑动窗口左侧字符不断弹出,也就是left不断右移,直到符合要求为止。
当滑动窗口的长度等于p的长度时,这时的s子字符串就是p的异位词。

curLeft和curRight表示字符串s中索引为left和right的字符在数组中的索引

public class LeetCode438 {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        if (s.length() < p.length()){
            return res;
        }
        //初始化空间
        int[] sCount = new int[26];
        int[] pCount = new int[26];
        //遍历p,把目标p中子串加入到pCount数组中
        for (int i = 0; i < p.length(); i++) {
            pCount[p.charAt(i) - 'a']++;
        }
        //left,right表示滑动窗口在字符串s中的索引下标
        int left = 0;
        for (int right = 0; right < s.length(); right++) {
            //获取字符串s中索引为right的字符在数组中的索引下标
            int curRight = s.charAt(right) - 'a';
            sCount[curRight]++;
            //左指针右移,缩小窗口
            while (sCount[curRight] > pCount[curRight]){
                int curLeft = s.charAt(left) - 'a';
                sCount[curLeft]--;
                left++;
            }
            //如果滑动窗口的长度和p的长度相等,则添加起始索引下标
            if (right - left + 1 == p.length()){
                res.add(left);
            }
        }
        return res;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34


方法二:滑动窗口 + 窗口

因为字符串中的字符全是小写字母,可以用长度为26的数组记录字母出现的次数
设n = len(s), m = len§。记录p字符串的字母频次p_cnt,和s字符串前m个字母频次s_cnt
若p_cnt和s_cnt相等,则找到第一个异位词索引 0
继续遍历s字符串索引为[m, n)的字母,在s_cnt中每次增加一个新字母,去除一个旧字母
判断p_cnt和s_cnt是否相等,相等则在返回值res中新增异位词索引 i - m + 1

public List<Integer> findAnagrams(String s, String p) {
    int n = s.length(), m = p.length();
    List<Integer> res = new ArrayList<>();
    if(n < m) return res;
    int[] pCnt = new int[26];
    int[] sCnt = new int[26];
    for(int i = 0; i < m; i++){
        pCnt[p.charAt(i) - 'a']++;
        sCnt[s.charAt(i) - 'a']++;
    }
    if(Arrays.equals(sCnt, pCnt)){
        res.add(0);
    }
    for(int i = m; i < n; i++){
        sCnt[s.charAt(i - m) - 'a']--;
        sCnt[s.charAt(i) - 'a']++;
        if(Arrays.equals(sCnt, pCnt)){
            res.add(i - m + 1);
        }
    }
    return res;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

时间复杂度:O(n),for循环有O(n),数组的长度是常数,所以数组的比较也是常数级别的,那最终的时间复杂度就是O(n)
空间复杂度:O(1),需要常数级别的额外空间

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/852862
推荐阅读
相关标签
  

闽ICP备14008679号