算法:找到字符串中所有字母异位词

题目:给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

我认为此题与 “查找无重复子串的最长子串” 的思考方向类似(我的随笔里写了这道算法,里面的讲解也很详细),但是这道题目更复杂。都使用哈希表来检查当前字符是不是目标字符,然后滑动左右指针来查找新的子串。

准备工具:左、右指针做滑动窗口;两个哈希表,pmap 存储 p 字符串的字符和频率,smap 存储每个滑动窗口中匹配到的目标字符和频率。

我在代码注释里写了非常清晰的解题步骤和解释!!请查看代码注释 ~

我的 Java 代码:

public List<Integer> findAnagrams(String s, String p) {
        Map<Character,Integer> pmap = new HashMap<>();
        Map<Character,Integer> smap = new HashMap<>();
        List<Integer> result = new ArrayList<>();
        int left = 0, right = 0;
        int currentLength = 0;
        
        // 设置pmap的元素及各自频率
        for(char c : p.toCharArray()){
            pmap.put(c,pmap.getOrDefault(c,0)+1);
        }

        // 右指针 “ 逐步 ” 往右遍历字符串
        while(right < s.length()){
            char c = s.charAt(right);
            //如果是目标元素,更新smap,并判断窗口长度有没有达到目标长度
            if(pmap.containsKey(c)){ 
                // 更新smap              
                smap.put(c, smap.getOrDefault(c,0)+1);
                
                //子串长度相等后,检查smap是否异位词,完全匹配就添加left到结果列表(因为left是子串起始索引)
                currentLength = right - left + 1;
                if(currentLength==p.length()){
                     if(smap.equals(pmap)){
                    result.add(left);
                }
                //如果窗口长度已经达到目标值,无论是不是异位词,都要移动左指针,删除左元素:把left元素数量在smap中减一(数量为0则移除该元素,否则影响长度匹配)。为了保证:每个窗口长度不能超过目标长度。
                char cleft = s.charAt(left);
                smap.put(cleft, smap.getOrDefault(cleft,0)-1);
                if(smap.get(cleft)==0) smap.remove(cleft);
                left ++ ;
                }
            }              
            // 如果不是目标字符,则把left移到当前字符的下一个字符,开启新窗口。为什么要这样移动左指针?因为当前left到right的这段区间都不是目标子串,所以要直接跳到right后面查找新子串。
            else{
                left = right+1;
                smap.clear();
            }

        right ++ ; 

        }
        return result;
    }
posted @ 2025-07-22 22:54  junjunyi  阅读(23)  评论(0)    收藏  举报