Loading

Medium | LeetCode 438. 找到字符串中所有字母异位词 | 滑动窗口

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

给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

字符串只包含小写英文字母,并且字符串 sp 的长度都不超过 20100。

说明:

  • 字母异位词指字母相同,但排列不同的字符串。
  • 不考虑答案输出的顺序。

示例 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" 的字母异位词。

解题思路

 public List<Integer> findAnagrams(String s, String p) {
    List<Integer> res = new ArrayList<>();
    if(s.length() < p.length() || s.length() == 0 || p.length() == 0) {
        return res;
    }
    // 统计模式串的各个字符的个数
    int[] alphaDiff = new int[26];
    for (int i = 0; i < p.length(); i++) {
        alphaDiff[p.charAt(i)-'a']++;
    }
    // 初始化窗口
    int start = 0, end = p.length();
    // 并统计窗口内字符的差异的个数, 即模式串各个字符, 比窗口内各个字符多出的数量
    // 如果这个差异数组的全部字符均为0, 则代表此字符串时异位词
    for (int i = start; i < end; i++) {
        alphaDiff[s.charAt(i) - 'a']--;
    }
    int slen = s.length();
    // 依次滑动窗口
    while (end <= slen) {
        boolean isAnagrams = true;
        // 判断当前窗口是否是字母异位词
        for (int alpha : alphaDiff) {
            if (alpha != 0) {
                isAnagrams = false;
                break;
            }
        }
        // 如果是字母异位词, 则添加进结果集
        if (isAnagrams) {
            res.add(start);
        }
        // 移动滑动窗口
        if (end < slen) {
            // 移除start
            alphaDiff[s.charAt(start) - 'a']++;
            // 将end添加进滑动窗口
            alphaDiff[s.charAt(end) - 'a']--;
        }
        start++;
        end++;
    }
    return res;
}
posted @ 2021-01-27 11:43  反身而诚、  阅读(57)  评论(0编辑  收藏  举报