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

题目链接

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

题目描述

找到字符串中所有字母异位词_第1张图片

注意点

  • 异位词 指由相同字母重排列形成的字符串(包括相同的字符串)
  • s 和 p 仅包含小写字母
  • 返回所有符合题意的子串的起始索引

解答思路

  • 根据双指针组成的窗口寻找字母异位词,存储p中各个字符出现的数量,在滑动窗口时,通过比较当前窗口中字符及对应数量与p中字符及对应数量判断当前窗口是否是字母异位词
  • 不断移动左指针与右指针找到字母异位词,在移动右指针时,会有以下几种情况:
    • 如果当前字符在p中不存在,则说明该窗口不可能组成字母异位词,可直接将左指针移动到右指针处,创造一个新窗口
    • 如果当前字符添加后整个窗口中该字符数量多于p中该字符数量,则需要移动左指针直到窗口内该字符数量和p中该字符数量相同(也就是窗口中从左往右找到第一个等于当前字符的字符)
    • 如果当前字符不多于p中字符数量且此时窗口长度等于p的长度,说明找到了字母异位词,将左指针添加到结果集中,并将窗口往右移动一格
    • 如果当前字符不多于p中字符数量且此时窗口长度小于p的长度,则需要移动右指针增加窗口大小继续寻找字母异位词

代码

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        // 记录p中字符及对应数量
        int[] targetArr = new int[26];
        for (int i = 0; i < p.length(); i++) {
            targetArr[p.charAt(i) - 'a'] += 1;
        }
        // 记录窗口中字符及对应数量
        int[] currArr = new int[26];
        int currLen = 0;
        int left = 0;
        for (int right = 0; right < s.length(); right++) {
            // 该窗口内的字符串不可能组成字母异位词,创建新窗口
            if (targetArr[s.charAt(right) - 'a'] == 0) {
                currArr = new int[26];
                currLen = 0;
                left = right + 1;
                continue;
            }
            // 该字符已超过p中该字符数量,窗口向右移动
            if (currArr[s.charAt(right) - 'a'] >= targetArr[s.charAt(right) - 'a']) {
                while (s.charAt(left) != s.charAt(right)) {
                    currArr[s.charAt(left) - 'a'] -= 1;
                    currLen--;
                    left++;
                }
                left++;
                continue;
            }
            currArr[s.charAt(right) - 'a'] += 1;
            currLen++;
            // 找到了字母异位词,窗口向右移动
            if (currLen == p.length()) {
                res.add(left);
                currArr[s.charAt(left) - 'a'] -= 1;
                currLen--;
                left++;
            }
        }
        return res;
    }
}

关键点

  • 滑动窗口的思想

你可能感兴趣的:(算法TOP100,数据结构,leetcode,算法,java)