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

Posted 三笠·阿卡曼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode #438 找到字符串中所有字母异位词相关的知识,希望对你有一定的参考价值。

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

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

说明:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string

示例

在这里插入图片描述

最佳代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author vleus
 * @date 2021年05月13日 22:51
 */
public class FindALLAnagrams {

    //方法一: 枚举所有长度为p.length()的子串
    public List<Integer> findAnagrams1(String s, String p) {

        //定义一个结果列表
        ArrayList<Integer> result = new ArrayList<>();

        //1、统计p中所有字符出现的频次
        int[] pCharCounts = new int[26];

        for (int i = 0; i < p.length(); i++) {
            pCharCounts[p.charAt(i) - 'a']++;
        }

        //2、遍历s,以每一个字符作为起始,考察长度为p.length()的子串
        for (int i = 0; i <= s.length() - p.length(); i++) {
            //3、判断当前子串是否为p的字母异位词
            boolean isMatched = true;

            int[] subStrCharCounts = new int[26];
            for (int j = i; j < i + p.length(); j++) {
                subStrCharCounts[s.charAt(j) - 'a']++;

                //判断当前字符频次如果超过了p中的频次,就一定不符合要求
                if(subStrCharCounts[s.charAt(j) - 'a'] > pCharCounts[s.charAt(j) - 'a']){
                    isMatched = false;
                    break;
                }
            }
            if (isMatched) {
                result.add(i);
            }
        }
        return result;
    }

    //方法二:滑动窗口法,分别移动起始和结束位置
    public List<Integer> findAnagrams(String s, String p) {

        //定义一个结果列表
        ArrayList<Integer> result = new ArrayList<>();

        //1、统计p中所有字符出现的频次
        int[] pCharCounts = new int[26];

        for (int i = 0; i < p.length(); i++) {
            pCharCounts[p.charAt(i) - 'a']++;
        }

        //统计子串中所有字符出现频次的数组
        int[] subStrCharCounts = new int[26];

        //定义起始和结束位置
        int start = 0,end = 1;
        //2.移动指针,总是截取字符串出现频次全部小于等于p中字符频次的子串
        while (end <= s.length()) {
            char newChar = s.charAt(end - 1);
            subStrCharCounts[newChar - 'a']++;

            //3.判断当前子串是否符合要求
            //如果新增字符导致子串频次超出了p中频次,那么移动start,消除新增的字符的影响
            while (subStrCharCounts[newChar - 'a'] > pCharCounts[newChar - 'a'] && start < end) {
                char removedChar = s.charAt(start);
                subStrCharCounts[removedChar - 'a']--;
                start++;
            }

            //如果当前子串等于p的长度,那么就是一个字母异位词
            if (end - start == p.length()) {
                result.add(start);
            }

            end++;
        }

        return result;
    }

    public static void main(String[] args) {

        String s = "cbaebabacd";
        String p = "abc";

        FindALLAnagrams findALLAnagrams = new FindALLAnagrams();

        System.out.println(Arrays.toString(findALLAnagrams.findAnagrams(s,p).toArray()));

    }
}

以上是关于LeetCode #438 找到字符串中所有字母异位词的主要内容,如果未能解决你的问题,请参考以下文章

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

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

LeetCode 438 找到字符串中所有字母异位词[数组 滑动窗口] HERODING的LeetCode之路

leetcode 438. 找到字符串中所有字母异位词(Find All Anagrams in a String)

LeetCode 438. 找到字符串中所有字母异位词 / 786. 第 K 个最小的素数分数 / 400. 第 N 位数字(优先队列,二分+双指针)

滑动窗口同数组的结合(LeetCode 438.找到字符串中所有字母异位词&567.字符串的排列)