LeetCode算法题-Find All Anagrams in a String(Java实现)

这是悦乐书的第228次更新,第240篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第95题(顺位题号是438)。给定一个字符串s和一个非空字符串p,找到s中p的字谜的所有起始索引。字符串仅由小写英文字母组成,字符串s和p的长度不会大于20,100。输出顺序无关紧要。例如:

输入:s:“cbaebabacd” p:“abc”

输出:[0,6]

说明:

起始索引等于0的子字符串是“cba”,它是“abc”的字谜。

起始索引等于6的子字符串是“bac”,它是“abc”的字谜。

输入:s:“abab”p:“ab”

输出:[0,1,2]

说明:

起始索引等于0的子字符串是“ab”,它是“ab”的字谜。

起始索引等于1的子字符串是“ba”,它是“ab”的字谜。

起始索引等于2的子字符串是“ab”,它是“ab”的字谜。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

题目的意思是在s中寻找由p中字符任意组成的字符串的起始索引。我们可以先将p中的字符及其出现次数存入一个256大小的整型数组,然后使用循环,从s的第一位字符开始,如果从第1位到p的长度位的字符都能匹配,那么就将起始索引添加进list中。

第一,为了多次使用存有p字符及其出现次数的数组,我们使用Arrays.copyOf方法,每次复制出一个新数组来处理,不影响原数组中的值。

第二,如果当前字符作为起始无法匹配,那么就结束内层循环,进入s下一个字符继续开始。

第三,因为是连续判断p的长度位,所以外层循环的次数控制为s的长度减去p的长度,直接使用s的长度会报下标越界异常。

public List<Integer> findAnagrams(String s, String p) {
    List<Integer> list = new ArrayList<Integer>();
    if (s == null || s.length() == 0 || s.length() < p.length()) {
        return list;
    }
    int[] arr = new int[256];
    for (char ch : p.toCharArray()) {
        arr[ch]++;
    }
    int len = p.length();
    for (int i=0; i<=s.length()-len; i++) {
        boolean isMatch = true;
        int[] arr2 = Arrays.copyOf(arr, 256);
        for (int j=i; j<i+len; j++) {
            if (--arr2[s.charAt(j)] < 0) {
                isMatch = false;
                break;
            }
        }
        if (isMatch) {
            list.add(i);
        }
    }
    return list;
}

03 第二种解法

对于第一种解法,我们可以再简化下,同样是使用256大小的整型数组,但是我们将s也添加进256大小的数组中去。

先从0开始,将p中的字符及其出现次数添加进pArr数组中,同时将s中的前p的长度个字符添加进sArr数组中,进行第一次的比较,如果两数组相同,那么就将索引0添加进list中。接着,开始循环处理s中剩下的字符。

从p的长度开始作为循环的起始索引,往sArr中添加当前字符出现的次数,同时将s中左边字符出现的次数进行移除,即往sArr中添加新数的同时,移除旧数,然后判断两数组是否相等,相等就将起始索引添加进list中。

在本解法中,判断两数组是否相同使用的是Arrays.equals方法。

public List<Integer> findAnagrams2(String s, String p) {
    List<Integer> list = new ArrayList<Integer>();
    if (s == null || s.length() == 0 || s.length() < p.length()) {
        return list;
    }
    int[] pArr = new int[256];
    int[] sArr = new int[256];
    for(int i=0; i<p.length(); i++){
        pArr[p.charAt(i)]++;
        sArr[s.charAt(i)]++;
    }
    if (Arrays.equals(pArr, sArr)) {
        list.add(0);
    }
    for (int j=p.length(); j<s.length(); j++) {
        ++sArr[s.charAt(j)];
        --sArr[s.charAt(j-p.length())];
        if (Arrays.equals(pArr, sArr)) {
            list.add(j-p.length()+1);
        }
    }
    return list;
}

04 第三种解法

使用双指针。先将p中的字符及其出现次数初始化进256大小的整型数组,然后定义三个变量,第一个指针从0开始,表示从左,第二个指针也从0开始,表示向右,第三个变量为count,初始值为p的长度。

每次进入循环时,都将右指针向前移动1个单位,如果当前s中的字符存在于数组中,count减1,如果count等于0,则表示已经找到了s中满足p长度的字符串,此时就将左指针添加进list中。如果右指针减去左指针的大小等于p的长度,说明已经判断完一个p长度的字符串了,就需要将左指针往前移动一个单位,并且左指针指向的字符存在于数组中,count加1,最后返回list。

public List<Integer> findAnagrams3(String s, String p) {
    List<Integer> list = new ArrayList<Integer>();
    if (s == null || s.length() == 0 || s.length() < p.length()) {
        return list;
    }
    int[] arr = new int[256];
    for (char ch : p.toCharArray()) {
        arr[ch]++;
    }
    int left = 0, right = 0, count = p.length();
    while (right < s.length()) {
        if (arr[s.charAt(right++)]-- >= 1) {
            count--;
        }
        if (count == 0) {
            list.add(left);
        }
        if (right - left == p.length() && arr[s.charAt(left++)]++ >= 0) {
            count++;
        }
    }
    return list;
}

05 小结

算法专题目前已连续日更超过两个月,算法题文章95+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

原文地址:https://www.cnblogs.com/xiaochuan94/p/10260710.html

时间: 2024-07-29 21:53:40

LeetCode算法题-Find All Anagrams in a String(Java实现)的相关文章

LeetCode算法题-N-ary Tree Level Order Traversal(Java实现)

这是悦乐书的第225次更新,第238篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第92题(顺位题号是429).给定n-ary树,返回其节点值的级别顺序遍历.(即,从左到右,逐级).例如,给定一个3-ary树: 我们应该返回它的级别顺序遍历: [[1],[3,2,4][5,6]] 注意: 树的深度最多为1000. 节点总数最多为5000. 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 02

LeetCode算法题-Convert BST to Greater Tree(Java实现)

这是悦乐书的第255次更新,第268篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第122题(顺位题号是538).给定二进制搜索树(BST),将其转换为更大树,使原始BST的每个键都更改为原始键加上所有键的总和大于BST中的原始键.例如: 输入:二进制搜索树的根,如下所示: 5 / 2 13 输出:大树的根,如下所示: 18 / 20 13 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 0

LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)

这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个不同节点的值之间的最小差值.示例: 给定的树[4,2,6,1,3,null,null]由下图表示: 4 / 2 6 / \ 1 3 输出:1 说明:请注意,root是TreeNode对象,而不是数组.该树中的任意节点最小差值为1,它发生在节点1和节点2之间,也发生在节点3和节点2之间. 注意: BS

LeetCode算法题-Number of Lines To Write String(Java实现)

这是悦乐书的第319次更新,第340篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第188题(顺位题号是806).我们要将给定字符串S的字母从左到右写成行.每行最大宽度为100个单位,如果写一个字母会导致该行的宽度超过100个单位,则会写入下一行.给出一个数组宽度,一个数组,其中widths[0]是'a'的宽度,widths[1]是'b'的宽度,widths[25]是'z'的宽度. 现在回答两个问题:S中至少有一个字符有多少行,最后一行使用的宽度是多少?将答案作为长

LeetCode算法题-Maximize Distance to Closest Person(Java实现)

这是悦乐书的第328次更新,第351篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第198题(顺位题号是849).在一排座位中,1表示一个人坐在该座位上,0表示座位是空的.在这些座位中,至少有一个空座位,至少有一个人坐着.Alex想坐在座位上,以便他和离他最近的人之间的距离最远.返回距离最近的人的最大距离.例如: 输入:[1,0,0,0,1,0,1] 输出:2 说明:如果Alex坐在第二个空座位(seats[2]),那么离最近的人距离为2.如果Alex坐在任何其他空

Leetcode 算法题--ReverseWordsInString

翻转字符串,想到什么写什么...我的做法是先trim掉空格,然后从字符串尾部开始扫描,遇到空格则认为一个单词结束,然后copy这个单词.需要注意的地方在于当扫描到最后一个单词的第一个字母时(譬如the sky is blue的t字母),注意单词长度的自增逻辑. 网上还有人的做法是反转整个字符串,然后逐个翻转单词. 1 package edu.hust.sse.Problems; 2 3 //Given s = "the sky is blue", 4 //return "bl

【leetcode刷题笔记】Anagrams

Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will be in lower-case. 题解: 所谓的anagrams,只若干个词,它们包含的字母的个数和种类完全一样,只是字符的顺序不一样.比如说bus,usb,sub就是一组angrams.同一组angrams具有排序后相同的特点,比如对上述三个单词按字典序排序分别得到bsu,bsu,bsu.我们用这一点

【算法】LeetCode算法题-Count And Say

这是悦乐书的第153次更新,第155篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第12题(顺位题号是38).count-and-say序列是整数序列,前五个术语如下: 1 11 21 1211 111221 1被读作"一个一"或者11.第二项的值是第一项的读法. 11被读作"两个一"或者21.第三项的值是第二项的读法. 21被读作"一个二,两个一"或者1211.第四项的值是第三项的读法. 给定整数n,其中1≤n≤3

【算法】LeetCode算法题-Length Of Last Word

这是悦乐书的第155次更新,第157篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第14题(顺位题号是58).给定一个字符串,包含戴尔字母.小写字母和空格,返回最后一个单词的长度,如果最后一个单词不存在则返回0.另外,单词不包含空格.例如: 输入: "Hello World" 输出: 5 说明:最后一个单词为world,其长度为5 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 0