跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

滑动窗口进阶:数组模拟哈希表解无重复字符最长子串

无重复字符的最长子串问题要求找出字符串中最长的连续且不包含重复字符的子串。本文对比了暴力解法与滑动窗口优化方案,指出暴力法因重复统计导致 O(N²) 的时间开销。通过引入双指针和数组模拟哈希表,利用滑动窗口动态维护字符频次,将复杂度降至 O(N)。核心在于发现重复时仅移动左指针收缩窗口,而非重置统计信息。

赛博朋克发布于 2026/2/13更新于 2026/10/1793 浏览
滑动窗口进阶:数组模拟哈希表解无重复字符最长子串

上期回顾

在之前的滑动窗口练习中,我们处理过类似最小覆盖子串的问题。滑动窗口的核心套路其实相对固定,关键在于如何维护窗口内的状态。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int left = 0, right = 0, length = n + 1, sum = 0;
        while (right < nums.size()) {
            sum += nums[right];
            while (sum >= target) {
                length = min(right - left + 1, length);
                sum -= nums[left++];
            }
            right++;
        }
        return length == n + 1 ? 0 : length;
    }
};

本期题目:无重复字符的最长子串

问题描述

给定一个字符串 s,请你找出其中不含有重复字符的 最长子串 的长度。

关键点分析

  • 无重复:窗口内字符不能重复出现。
  • 统计频次:需要知道每个字符出现的次数(使用哈希表)。
  • 最长:目标是最大化窗口长度。
  • 子串:必须是连续的,不能跳跃。

暴力解法

最直观的思路是枚举所有可能的子串,检查是否包含重复字符。

双重循环 + 哈希表统计

外层循环确定起点,内层循环扩展终点。每次进入新的起点时,重置哈希表重新统计。如果发现重复字符,立即停止当前起点的遍历。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size(), ret = 0;
        for (int i = 0; i < n; i++) {
            int hash[128] = {0}; // 使用数组模拟哈希表,每次外循环刷新
            for (int j = i; j < n; j++) {
                hash[s[j]]++;
                if (hash[s[j]] > 1) {
                    ret = max(ret, j - i);
                    break; // 有重复字符的情况
                }
            }
            ret = max(ret, j - i); // 处理无重复字符的情况
        }
        return ret;
    }
};

时间复杂度为 $O(N^2)$。虽然能通过部分测试用例,但存在明显的性能瓶颈:每次遇到重复字符后,我们放弃了当前的统计结果,下一次遍历时又重新计算了一遍之前已经统计过的数据。

优化思路:滑动窗口

既然暴力解法浪费了大量重复计算的资源,我们可以尝试对之前的统计数据进行维护,而不是每次都从头开始。

观察发现,当右指针向右移动遇到重复字符时,我们不需要把整个窗口清空,只需要将左指针向右移动,直到移除导致重复的那个字符即可。这就是典型的同向双指针模型,也就是滑动窗口。

通过这种机制,每个字符最多被访问两次(一次进窗口,一次出窗口),时间复杂度可以优化到 $O(N)$。

算法逻辑
  1. 初始化:定义左右指针 left, right,以及用于计数的数组 hash[128]。
  2. 进窗口:右指针向右移动,将字符加入计数。
  3. 条件判断:如果某字符计数大于 1,说明出现重复,开始收缩窗口。
  4. 出窗口:左指针向右移动,减少对应字符的计数,直到重复消除。
  5. 更新结果:每次窗口合法时,更新最大长度。

代码实现

下面直接上优化后的 C++ 实现,注意数组模拟哈希表的细节。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size();
        int hash[128] = {0}; // ASCII 码范围足够用 128 大小的数组
        int left = 0, right = 0, ret = 0;
        
        while (right < n) {
            // 进窗口:统计当前字符
            hash[s[right]]++;
            
            // 如果当前字符重复,收缩左边界
            while (hash[s[right]] > 1) {
                hash[s[left]]--;
                left++;
            }
            
            // 更新最大长度
            ret = max(ret, right - left + 1);
            right++;
        }
        
        return ret;
    }
};

总结

这道题是滑动窗口的经典应用。相比于暴力解法,优化的关键在于动态维护窗口状态。只要理解了'右扩左缩'的逻辑,这类题目就能迎刃而解。

目录

  1. 上期回顾
  2. 本期题目:无重复字符的最长子串
  3. 问题描述
  4. 关键点分析
  5. 暴力解法
  6. 双重循环 + 哈希表统计
  7. 优化思路:滑动窗口
  8. 算法逻辑
  9. 代码实现
  10. 总结

更多推荐文章

查看全部
  • Qwen2.5-7B 客服机器人云端对接微信指南
  • PyCharm 集成 GitHub Copilot 安装与配置指南
  • 多模态技术综述:从视觉表征到多模态大模型
  • SpringBoot 配置文件核心用法:Properties 与 YAML
  • Spring Boot 数据导入导出与报表生成实战
  • 网络安全护网行动参与指南与薪资概况
  • FPGA 实现高速数字信号处理的设计本质与实战
  • Spring AOP 的代理模式与动态代理:从原理到源码
  • 几款支持万方平台的 AIGC 降重工具实测对比
  • Cursor 在 C/C++ 开发中的实战使用指南
  • 在 Linux 上把 OpenClaw 接到 QQ 机器人
  • AI 大模型时代:工程师与项目管理者的机遇与挑战
  • LangChain 使用知识库修复大模型幻觉问题
  • 基于 YOLO 标注格式的无人机航拍人员搜救检测数据集
  • 基于实际案例的 AI 大模型应用与提示词工程实践指南
  • Llama.cpp 跨平台部署实战:本地运行大模型完整指南
  • 转行 AI 产品经理:面试核心问题与准备指南
  • 本地部署 Wan2.1 视频生成模型及远程访问配置
  • RTX50 系列显卡与 CUDA、PyTorch、Python 版本对应关系
  • 字节跳动 AI 产品经理三轮面试经验与通用问题解析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online