14.LeetCode 438 题解:滑动窗口+哈希表找所有字母异位词

目录

一、题目解析

二、讲解算法原理

[1. 如何快速判断两个字符串是否是"异位词"?](#1. 如何快速判断两个字符串是否是“异位词”?)

[2. 解决问题:滑动窗口 + 哈希表](#2. 解决问题:滑动窗口 + 哈希表)

[三、解决问题(滑动窗口 + 哈希表流程)](#三、解决问题(滑动窗口 + 哈希表流程))

四、优化:更新结果的判断条件

五、完整代码(Java)


一、题目解析

题目:438. 找到字符串中所有字母异位词

链接:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

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

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

示例 1:

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

输出:[0, 6]

解释:起始索引等于 0 的子串是 "cba",它是 "abc"的异位词;起始索引等于 6 的子串是 "bac",它是 "abc"的异位词。

示例 2:

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

输出:[0, 1, 2]

二、讲解算法原理

1. 如何快速判断两个字符串是否是"异位词"?

利用哈希表。例如:

  • 字符串 s1 = "aabca":统计每个字符出现次数 → a→3, b→1, c→1(记为 hash1)。

  • 字符串 s2 = "abaca":统计每个字符出现次数 → a→3, b→1, c→1(记为 hash2)。

    若 hash1和 hash2完全相同,则两字符串是异位词。

2. 解决问题:滑动窗口 + 哈希表

核心思路:用滑动窗口 维护 s中与 p长度相同的子串,用哈希表 统计窗口内字符与 p的字符频次,判断是否匹配。

三、解决问题(滑动窗口 + 哈希表流程)

  1. 初始化窗口:left = 0, right = 0。

  2. 进窗口:将 s[right]加入窗口,更新窗口字符的哈希表(hash2)。

  3. 判断窗口长度:若 right - left + 1 > p.length(),则需要出窗口(移除 s[left]),更新 hash2。

  4. 更新结果:检查 hash2与 p的哈希表(hash1)是否匹配,若匹配则记录起始索引 left。

四、优化:更新结果的判断条件

利用变量 count统计窗口中"有效字符"的个数(即窗口内字符频次 ≤ p中对应字符频次的字符数量)。

  • 进窗口 :进入字符后,若 hash2[in] ≤ hash1[in],则 count++(说明该字符是"有效"的)。

  • 出窗口 :离开字符前,若 hash2[out] ≤ hash1[out],则 count--(说明该字符离开后,"有效"字符减少)。

  • 更新结果 :当 count == p.length()时,说明窗口内所有字符都"有效",即找到异位词,记录 left。

五、完整代码(Java)

java 复制代码
class Solution {
    public List<Integer> findAnagrams(String ss, String pp) {
        List<Integer> ret = new ArrayList<Integer>();
        char[] s = ss.toCharArray();
        char[] p = pp.toCharArray();

        int[] hash1 = new int[26]; // 统计字符串 p 中每一个字符出现的个数
        for (char ch : p)
            hash1[ch - 'a']++;

        int[] hash2 = new int[26]; // 统计窗口中每一个字符出现的个数
        int m = p.length;
        for (int left = 0, right = 0, count = 0; right < s.length; right++) {
            char in = s[right];
            if (++hash2[in - 'a'] <= hash1[in - 'a'])
                count++; // 进窗口 + 维护 count
            if (right - left + 1 > m) // 判断窗口长度是否超过 p 的长度
            {
                char out = s[left++];
                if (hash2[out - 'a']-- <= hash1[out - 'a'])
                    count--; // 出窗口 + 维护 count
            }
            // 更新结果:当 count == m 时,说明窗口内是异位词
            if (count == m)
                ret.add(left);
        }
        return ret;
    }
}
相关推荐
一去不复返的通信er4 小时前
力扣-图论-岛屿数量
算法·leetcode·图论
wangchunyu1146 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
paopaokaka_luck6 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
Thomas.Sir6 小时前
第9课:SpringBoot4.x Web开发基础:WebMvc自动配置、静态资源、请求参数接收
java·spring boot
程序 代码狂人7 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
HDU-Dade7 小时前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
2501_944521597 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
Xin7708 小时前
LeetCode 79. 单词搜索(DFS 回溯法)
leetcode
南归北隐9 小时前
Spring AI Alibaba Graph框架实现MCP数据库查询实战
java·后端·spring ai·mcp·spring ai mcp
古法老登瞎折腾9 小时前
大数据智能运维实战(九):让 AI 查日志——找到异常,也保留上下文
java·大数据·运维·人工智能·spring ai·mcp