首页 > 其他分享 >[数组滑动窗口] 0438. 找到字符串中所有字母异位词

[数组滑动窗口] 0438. 找到字符串中所有字母异位词

时间:2024-12-03 12:29:25浏览次数:6  
标签:子串 0438 right 字符 异位 window need 滑动 left

文章目录

1. 题目链接


https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/



2. 题目大意

描述:给定两个字符串 s 和 p。

要求:找到 s 中所有 p 的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

说明

  • 异位词:指由相同字母重排列形成的字符串(包括相同的字符串)。
  • 1<=s.length,p.length<=3∗104。
  • s 和 p 仅包含小写字母。


3. 示例

输入: 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" 的异位词。



4. 解题思路

思路 1:滑动窗口

维护一个固定长度为 len§ 的滑动窗口。于是问题的难点变为了如何判断 s 的子串和 p 是异位词。可以使用两个字典来分别存储 s 的子串中各个字符个数和 p 中各个字符个数。如果两个字典对应的键值全相等,则说明 s 的子串和 p 是异位词。但是这样每一次比较的操作时间复杂度是 O(n),我们可以通过在滑动数组中逐字符比较的方式来减少两个字典之间相互比较的复杂度,并用 valid 记录经过验证的字符个数。整个算法步骤如下:

  • 使用哈希表 need 记录 p 中各个字符出现次数。使用字典 window 记录 s 的子串中各个字符出现的次数。使用数组 res 记录答案。使用 valid 记录 s 的子串中经过验证的字符个数。使用 window‾size表示窗口大小,值为 len§。使用两个指针 left、right。分别指向滑动窗口的左右边界。
  • 一开始,left、right 都指向 0。
  • 如果 s[right] 出现在 need 中,将最右侧字符 s[right]加入当前窗口 window 中,记录该字符个数。并验证该字符是否和 need 中个对应字符个数相等。相等则验证的字符个数加 1,即 valid += 1
  • 如果该窗口字符长度大于等于 window‾size个,即 right−left+1≥window‾size。则不断右移 left,缩小滑动窗口长度。
    • 如果验证字符个数 valid 等于窗口长度 window‾size,则 s[left,right+1] 为 p 的异位词,所以将 left 加入到答案数组中。
    • 如果s[left] 在 need 中,则更新窗口中对应字符的个数,同时维护 valid 值。
  • 右移 right,直到 right≥len(nums) 结束。
  • 输出答案数组 res。


5. 参考代码

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        Map<Character, Integer> need = new HashMap<>();
        for (char ch : p.toCharArray()) {
            need.put(ch, need.getOrDefault(ch, 0) + 1);
        }
        Map<Character, Integer> window = new HashMap<>();
        int windowSize = p.length();
        List<Integer> res = new ArrayList<>();
        int left = 0, right = 0, valid = 0;
        while (right < s.length()) {
            char rightChar = s.charAt(right);
            if (need.containsKey(rightChar)) {
                window.put(rightChar, window.getOrDefault(rightChar, 0) + 1);
                if (window.get(rightChar).equals(need.get(rightChar))) {
                    valid++;
                }
            }
            if (right - left + 1 >= windowSize) {
                if (valid == need.size()) {
                    res.add(left);
                }
                char leftChar = s.charAt(left);
                if (need.containsKey(leftChar)) {
                    if (window.get(leftChar).equals(need.get(leftChar))) {
                        valid--;
                    }
                    window.put(leftChar, window.get(leftChar) - 1);
                }
                left++;
            }
            right++;
        }
        return res;
    }
}


标签:子串,0438,right,字符,异位,window,need,滑动,left
From: https://blog.csdn.net/apple_74262176/article/details/144121474

相关文章

  • [数组滑动窗口] 0220. 存在重复元素三
    文章目录1.题目链接2.题目大意3.示例4.解题思路5.参考代码1.题目链接https://leetcode.cn/problems/contains-duplicate-iii/description/2.题目大意描述:给定一个整数数组nums,以及两个整数k、t。要求:判断数组中是否存在两个不同下标的i和j,其对应......
  • LeetCode题练习与总结:找到字符串中所有字母异位词--438
    一、题目描述给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。示例 1:输入:s="cbaebabacd",p="abc"输出:[0,6]解释:起始索引等于0的子串是"cba",它是"abc"的异位词。起始索引等于6的子......
  • 【优选算法篇】一文读懂滑动窗口:动态调整范围的算法利器(上篇)
    文章目录须知......
  • 滑动窗口讲解(c基础)
    滑动窗口的基本概念滑动窗口是一种高效处理线性数据结构(如数组、字符串)的算法技巧。它就像是一个可移动的“框”,框住数据结构中的一部分元素,通过不断地移动这个“框”(即滑动窗口),对框内的元素进行分析和处理,以解决各种与子序列、子数组相关的问题。滑动窗口的组成部分窗......
  • 代码随想录第十一天|栈与队列part02--150.逆波兰表达式求值、239.滑动窗口最大值、347
    150.逆波兰表达式求值(150.逆波兰表达式求值)题目分析:计算逆波兰表达式(后缀表达式:左右中)的值,算符仅包含四则运算,操作数为一个整数或另一个表达式,整数除法向零截断(向下取整),无除零运算,答案及中间结果不超过32位,即使用整型int即可。解题重点:后缀表达式的每一个表达式中:读入1个算......
  • 滑动验证码之鼠标移动轨迹绘制分析
    Part1鼠标事件类型这些是JavaScript中与鼠标事件相关的常见事件类型。具体介绍如下:auxclick:表示鼠标的辅助按键被点击。辅助按键包括鼠标中键和右键。click:表示鼠标单击操作被触发。dblclick:表示鼠标双击操作被触发。mousedown:表示鼠标按下操作被触发。mouseup:表示鼠标......
  • 【验证码逆向专栏】某里 v2 滑动验证码分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作......
  • 【C++习题】16.滑动窗口_最小覆盖子串
    文章目录题目链接:题目描述:解法C++算法代码:图解题目链接:76.最小覆盖子串题目描述:解法暴力解法:列出所有符合要求的字串,然后比较大小。滑动窗口+哈希表比如,如果已经符合要求了那么left右移一位的话,right需要移动吗?left指向的地方恰好有符合t的字符,-......
  • 【C++习题】15.滑动窗口_串联所有单词的子串
    文章目录题目链接:题目描述:解法C++算法代码:图解题目链接:30.串联所有单词的子串题目描述:解法滑动窗口+哈希表这题和第14题不同的是:哈希表不同:hash<string,int>left与right指针的移动不同:移动的步长是每个单词的长度滑动窗口执行的次数不同C++算法代......
  • 【LC】239. 滑动窗口最大值
    题目描述:给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。示例1:输入:nums=[1,3,-1,-3,5,3,6,7],k=3输出:[3,3,5,5,6,7]解释......