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

滑动窗口算法实战:最小长度子数组与无重复字符最长子串

滑动窗口算法是处理连续子序列问题的利器。通过双指针动态维护窗口范围,配合哈希表或计数数组,可在线性时间内解决如最小长度子数组和无重复字符最长子串等典型题目。核心在于根据条件灵活移动左右边界,平衡窗口大小与约束条件,避免暴力枚举带来的性能瓶颈。

JavaCoder发布于 2026/3/24更新于 2026/10/24104 浏览
滑动窗口算法实战:最小长度子数组与无重复字符最长子串

滑动窗口算法实战

滑动窗口是处理连续子序列问题的经典技巧,特别适合解决涉及区间和、最值或特定条件的题目。通过维护一个动态变化的窗口范围,我们往往能将时间复杂度从 O(n²) 优化到 O(n)。下面结合两个典型例题来深入剖析。

1. 长度最小的子数组

问题描述

给定一个包含正整数的数组和一个目标值 target,找出和大于等于 target 的连续子数组的最小长度。如果不存在这样的子数组,返回 0。

思路解析

暴力枚举所有子数组需要 O(n²) 甚至 O(n³) 的时间,对于 n = 10⁵ 的数据规模显然会超时。注意到数组元素都是正整数,这意味着当右指针向右移动时,窗口内的和单调递增;反之,左指针向右移动时,和单调递减。这一性质允许我们使用滑动窗口进行优化。

核心策略是:

  • 扩展:右指针不断向右移动,将元素加入窗口。
  • 收缩:一旦窗口和满足条件(sum >= target),尝试移动左指针缩小窗口,同时更新最小长度。

这种双指针配合的方式保证了每个元素最多被访问两次,时间复杂度降为 O(n)。

代码实现 (C++)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len = INT_MAX;
        int n = nums.size();
        int sum = 0;
        
        for (int left = 0, right = 0; right < n; right++) {
            sum += nums[right]; // 进窗口
            
            while (sum >= target) { // 判断并收缩
                len = min(len, right - left + 1);
                sum -= nums[left++];
            }
        }
        return len == INT_MAX ? 0 : len;
    }
};

边界验证

实际编码时需留意几种特殊情况:

  • 数组中单个元素即满足条件。
  • 所有元素之和仍小于 target,此时应返回 0。
  • 初始化和变量类型是否溢出(本题为正整数,通常 int 足够)。

2. 无重复字符的最长子串

题目信息

  • 难度:中等
  • 标签:哈希表、字符串、滑动窗口

解法总结

方法时间复杂度空间复杂度
集合O(n)O(min(n, 128))
哈希表O(n)O(min(n, 128))
数组(推荐)O(n)O(1)

核心思路

这道题同样适用滑动窗口,但状态记录方式略有不同。我们需要维护一个不包含重复字符的窗口。

  1. 使用双指针 left 和 right 界定窗口。
  2. 利用数组或哈希表记录字符出现的次数(或最后出现的位置)。
  3. 当遇到重复字符时,左指针直接跳到重复字符上一次出现位置的下一个位置,或者逐步收缩直到重复消除。

这里采用计数数组的方法,当某个字符计数超过 1 时,说明窗口内存在重复,需收缩左边界。

代码实现 (C++)

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128] = {0};
        int ret = 0;
        int n = s.size();
        
        for (int left = 0, right = 0; right < n; right++) {
            hash[s[right]]++; // 进窗口
            
            while (hash[s[right]] > 1) { // 判断重复
                hash[s[left++]]--; // 出窗口
            }
            
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

复杂度分析

  • 时间复杂度:O(n),左右指针各遍历一次字符串。
  • 空间复杂度:O(1),固定大小的哈希数组(ASCII 码范围)。

小结

滑动窗口的关键在于理解何时扩张、何时收缩。对于这类题目,先明确约束条件(如和的大小、字符唯一性),再根据条件变化调整指针位置,就能高效解决问题。在实际面试或工程中,掌握这种模式能显著提升解题效率。

目录

  1. 滑动窗口算法实战
  2. 1. 长度最小的子数组
  3. 问题描述
  4. 思路解析
  5. 代码实现 (C++)
  6. 边界验证
  7. 2. 无重复字符的最长子串
  8. 题目信息
  9. 解法总结
  10. 核心思路
  11. 代码实现 (C++)
  12. 复杂度分析
  13. 小结

更多推荐文章

查看全部
  • Node.js 最新安装教程及环境变量配置
  • ASP.NET Core Web API 控制器及方法常用注解属性详解
  • C++ 泛型编程:代码复用的核心利器
  • Linux 内核源码中 asm 头文件的目录结构与链接实践
  • 昇腾 NPU 部署与测评 CodeLlama-7b-Python
  • OpenDroneMap 无人机影像三维重建部署与实战指南
  • OpenClaw 部署方案对比:云端、WSL、Mac 与虚拟机实战
  • STL 模型体积与质量计算 Python 工具使用指南
  • 基于 RoBERTa 模型的评论文本分类实战
  • OpenArm 开源机械臂技术框架与开发指南
  • 大模型分布式训练与高效调参技术实战
  • C++ 继承中的同名成员隐藏规则详解
  • OpenBCI + OpenViBE + Python: 实时运动想象小球控制系统
  • PPT 嵌入 VR 图片及全景图播放实操指南
  • 2024 大模型秋招面试高频问题与解答总结
  • MySQL 从下载到运行:详细安装配置教程
  • Rust 异步并发安全与内存管理实战指南
  • 基于子集选择算法的负载均衡方案
  • VS Code 禁用 Copilot 代码自动补全
  • Git 在 Windows 系统上的安装与配置教程

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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