图解LeetCode——438. 找到字符串中所有字母异位词

简介: 让枯燥的技术更简单

一、题目

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

二、示例

2.1> 示例 1:

输入】 s = "cbaebabacd", p = "abc"

输出】 [0,6]

解释

起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。

起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

2.2> 示例 2:

输入】 s = "abab", p = "ab"

输出】 [0,1,2]

解释

起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。

起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。

起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

  • 1 <= s.length, p.length <= 3 * 10^4
  • sp 仅包含小写字母

三、解题思路

根据题目描述,我们需要在字符串s中寻找p的异位词,那么我们可以通过双指针的方式,来进行对比和判断。

head指针】指向异位词子串的头元素,初始值为0

tail指针】指向异位词子串的尾元素的下一个元素位置,初始值为0

首先,我们创建128长度的数组int[] chars,然后遍历字符串p的每一个字符,并将对应的chars数组下标位置的值进行加1操作

初始化完数组chars之后,我们就可以通过遍历字符串s的每个字符,来判断是否符合异位词子串了。具体逻辑如下所示:

逻辑1】如果tail指针指向的字符,在chars中对应的值大于0,则执行减1操作,并且执行tail++

逻辑2】否则,获得head指针指向的字符,然后针对该字符在chars数组中的位置处执行加1操作,并且执行head++

逻辑3】当满足逻辑1的情况下,我们判断如果tail减去head等于p的长度,那么就说明我们找到了p的异位词子串,则将head复制给结果List即可。

好了,上面就是整道题的解题逻辑,我们还是通过举例来加深本题的理解。假设我们输入s = "cbaebabacd", p = "abc",针对前3个字符,我们发现都能在chars中找到,即:满足逻辑1。所以tail一直会移动到第3个下标位置。并且此时chars中所有元素都为0

因为chars数组中所有元素都是0,所以,满足逻辑2。那么head指针会进行移动,并且针对head指向的字符,都会在chars数组中进行加1操作。由于文章篇幅问题,仅画出了tail指针和head指针的移动过程。那么其余步骤就不再画了,并不影响对整道题目的理解。

四、代码实现

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> result = new ArrayList();
        int[] chars = new int[128];
        for (char c : p.toCharArray()) chars[c]++;
        int head = 0, tail = 0;
        char[] sc = s.toCharArray();
        while (tail < sc.length) {
            if (chars[sc[tail]] > 0) {
                chars[sc[tail++]]--;
                if ((tail - head) == p.length()) result.add(head);
            } else chars[sc[head++]]++;
        }
        return result;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

相关文章
|
2月前
|
存储 算法
LeetCode第49题字母异位词分组
LeetCode第49题"字母异位词分组"的解题方法,通过将每个字符串的字符排序后作为键存储在HashMap中,有效地将所有字母异位词分组。
LeetCode第49题字母异位词分组
|
2月前
|
存储 算法
LeetCode第43题字符串相乘
LeetCode第43题"字符串相乘"的解题方法,通过使用数组存储乘积并处理进位,避免了字符串转换数字的复杂性,提高了算法效率。
LeetCode第43题字符串相乘
|
2月前
|
算法 Java
LeetCode第28题找出字符串中第一个匹配项的下标
这篇文章介绍了LeetCode第28题"找出字符串中第一个匹配项的下标"的两种解法:暴力解法和KMP算法,并解释了KMP算法通过构建前缀表来提高字符串搜索的效率。
LeetCode第28题找出字符串中第一个匹配项的下标
|
2月前
|
算法
LeetCode第17题电话号码的字母组合
该文章介绍了 LeetCode 第 17 题电话号码的字母组合的解法,通过分析得出可使用递归和回溯的思想解决,避免循环穷举的高循环次数,并给出了具体的编码实现,同时总结了该题较难理解,需要了解递归的本质,当嵌套循环层次多时可考虑递归。
LeetCode第17题电话号码的字母组合
|
2月前
|
算法
LeetCode第8题字符串转换整数 (atoi)
该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
LeetCode第8题字符串转换整数 (atoi)
|
4月前
|
算法
力扣每日一题 6/23 字符串/模拟
力扣每日一题 6/23 字符串/模拟
31 1
|
4月前
|
索引
力扣每日一题 6/27 字符串 贪心
力扣每日一题 6/27 字符串 贪心
27 0
|
4月前
|
Python
力扣随机一题 模拟+字符串
力扣随机一题 模拟+字符串
24 0
|
5天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
44 6