Skip to content

找出字符串中所有字母异位词

理解题目:

题目要求在给定的字符串 s 中,找出所有是字符串 p 的字母异位词的子串,并返回这些子串的起始索引。

代码实现:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FindAllAnagramsInString {
    // 找出字符串中所有字母异位词的起始索引
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> result = new ArrayList<>(); // 存储结果的列表
        if (s == null || s.length() == 0 || p == null || p.length() == 0 || s.length() < p.length()) {
            return result; // 边界条件处理
        }

        // 统计目标字符串 p 中字符的频率
        Map<Character, Integer> pFreq = new HashMap<>();
        for (char c : p.toCharArray()) {
            pFreq.put(c, pFreq.getOrDefault(c, 0) + 1);
        }

        // 使用滑动窗口在字符串 s 上进行遍历
        Map<Character, Integer> windowFreq = new HashMap<>(); // 存储当前窗口内字符的频率
        int left = 0, right = 0, match = 0; // 左右指针和匹配字符数量

        while (right < s.length()) {
            char rightChar = s.charAt(right);
            if (pFreq.containsKey(rightChar)) {
                windowFreq.put(rightChar, windowFreq.getOrDefault(rightChar, 0) + 1);
                if (windowFreq.get(rightChar).equals(pFreq.get(rightChar))) {
                    match++;
                }
            }
            right++;

            // 如果滑动窗口包含了 p 的所有字符,则找到一个字母异位词,将起始索引添加到结果中
            while (match == pFreq.size()) {
                if (right - left == p.length()) {
                    result.add(left);
                }

                char leftChar = s.charAt(left);
                if (pFreq.containsKey(leftChar)) {
                    windowFreq.put(leftChar, windowFreq.get(leftChar) - 1);
                    if (windowFreq.get(leftChar) < pFreq.get(leftChar)) {
                        match--;
                    }
                }
                left++;
            }
        }

        return result;
    }
}

步骤解释:

1. 创建一个结果列表 result 用于存储找到的字母异位词的起始索引。

2. 首先对边界条件进行处理,如果字符串 s 为空,字符串 p 为空,或者字符串 s 的长度小于字符串 p 的长度,则直接返回空结果列表。

3. 统计字符串 p 中每个字符的出现次数,使用哈希表 pFreq 存储字符频率。

4. 使用滑动窗口在字符串 s 上进行遍历,初始化左右指针 leftright,以及匹配字符数量 match

5. 遍历字符串 s,将字符加入窗口并更新窗口中字符的频率。

6. 如果窗口中的字符频率与字符串 p 中的字符频率相匹配,则增加匹配字符数量 match

7. 如果 match 等于字符串 p 中字符数量,则说明找到一个字母异位词,将起始索引添加到结果列表中。

8. 左指针向右移动,缩小窗口,继续遍历直到遍历完整个字符串 s。