【Hot 100 刷题计划】 LeetCode 438. 找到字符串中所有字母异位词 | C++ 滑动窗口题解

LeetCode 438. 找到字符串中所有字母异位词 | C++ 固定滑动窗口极致优化题解

📌 题目描述

题目级别:中等

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

  • 异位词 :指由相同字母重排列形成的字符串(包括相同的字符串)。换句话说,异位词就是字符种类相同,且每种字符出现次数也相同的字符串。

  • 示例 1:

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

    输出: [0,6]

    解释:

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

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


💡 解题思路:固定长度的滑动窗口

寻找连续的子串,必然用到滑动窗口

由于异位词的一个重要前提是长度必须相等 ,所以我们不需要像通常的滑动窗口那样频繁地收缩和扩张,这道题的窗口大小是固定 的,恒等于 p.size()

核心步骤:

  1. 频次统计:我们要判断两个字符串是否互为异位词,只需要判断它们包含的字符频次是否完全一致。
  2. 初始化窗口 :先统计字符串 p 的字符频次,并在字符串 s 中框出前 p.size() 个字符,统计这个初始窗口的字符频次。如果两者相等,就把索引 0 加入结果集。
  3. 整体平移 :窗口开始向右滑动。每次滑动,实际上就是**"吃进"一个右边的新字符,同时"吐出"**一个左边的旧字符。
  4. 状态比对 :每次滑动后,比对当前窗口的频次和 p 的频次是否相同,如果相同,就记录当前窗口的起始索引。

🚀 性能优化杀手锏:数组代替哈希表

在判断频次时,普通哈希表(unordered_map)有较大的常数级时间开销。

由于题目限定了只包含 26 个小写英文字母 ,我们完全可以使用 vector<int>(26, 0) 或者单纯的整型数组来代替哈希表。在 C++ 中,vector 也是重载了 == 运算符的,可以直接比较两个 vector 是否完全一致!


💻 C++ 代码实现 (数组哈希优化版)

cpp 复制代码
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> res;
        int m = s.size(), n = p.size();
        
        // 长度不够,直接返回空
        if (m < n) return res;

        // 使用长度为 26 的 vector 代替哈希表,性能极高
        vector<int> p_cnt(26, 0);
        vector<int> win_cnt(26, 0);

        // 1. 初始化目标字符串 p 的频次,以及 s 中第一个窗口的频次
        for (int i = 0; i < n; i++) {
            p_cnt[p[i] - 'a']++;
            win_cnt[s[i] - 'a']++;
        }

        // 判断第一个窗口是否符合条件
        if (p_cnt == win_cnt) {
            res.push_back(0);
        }

        // 2. 窗口开始整体向右平移
        // i 指向即将移入窗口的右侧新字符
        for (int i = n; i < m; i++) {
            // 右边吃进一个新字符
            win_cnt[s[i] - 'a']++;
            // 左边吐出一个旧字符 (i - n 是滑出窗口的那个字符的索引)
            win_cnt[s[i - n] - 'a']--;

            // 直接比较两个 vector 是否完全一致
            if (p_cnt == win_cnt) {
                // i 是窗口右边界,减去长度 n 再加 1,就是窗口的起始索引
                res.push_back(i - n + 1);
            }
        }

        return res;
    }
};
相关推荐
春蕾夏荷_7282977253 小时前
c++ 编译abseil-cpp
c++·abseil-cpp
如竟没有火炬3 小时前
至少有K个重复字符的最长子串
开发语言·数据结构·python·算法·leetcode·动态规划
想带你从多云到转晴3 小时前
优选算法---双指针
java·算法
小O的算法实验室3 小时前
2026年IEEE TSMC,基于Q学习平衡全局与局部搜索的防空资源分配问题进化算法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
谙弆悕博士4 小时前
快速学C语言——第17章:多文件编程与头文件规范
c语言·开发语言·算法·学习方法·头文件·多文件编程
水蓝烟雨4 小时前
2359. 找到离给定两个节点最近的节点
算法·leetcode
ComputerInBook4 小时前
C++ 17 相比 C++ 14 新增之特征
开发语言·c++·c++ 17
澈2074 小时前
哈希表:O(1)查找的终极指南
算法·哈希算法·散列表
Peter·Pan爱编程4 小时前
引用:比指针更安全的别名
c++·指针·引用·c++基础
m0_502724954 小时前
golang 、java、c++、javascript 语言switch case异同
java·javascript·c++·golang