【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?

⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///


WARNING : DETECTING HIGH ENERGY

🌊 🌉 🌊 心手合一 · 水到渠成

|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| >>> ACCESS TERMINAL <<< ||
| 🦾 作者主页 | 🔥 C++初阶 |
| 💾C++进阶 | 📡 代码仓库 |


Running Process: 100% | Latency: 0ms


索引与导读

  • 前言
    • 一、什么是滑动窗口?
      • [1.1 核心机制:左右边界的律动](#1.1 核心机制:左右边界的律动)
      • [1.2 🖼️ 滑动窗口动态演示:寻找和为 7 的连续子数组](#1.2 🖼️ 滑动窗口动态演示:寻找和为 7 的连续子数组)
    • 二、滑动窗口的两大分类
      • [2.1 固定窗口](#2.1 固定窗口)
      • [2.2 可变窗口](#2.2 可变窗口)
    • 三、滑动窗口的通用模板
      • [3.1 解题思路模板](#3.1 解题思路模板)
      • [3.2 代码模板](#3.2 代码模板)
    • 四、滑动窗口的使用时机
    • 五、滑动窗口典型算法题目
      • [5.1 长度最小的子数组](#5.1 长度最小的子数组)
      • [5.2 无重复字符的最长子串](#5.2 无重复字符的最长子串)
      • [5.3 最大连续 1 的个数 III](#5.3 最大连续 1 的个数 III)
      • [5.4 将 x 减到 0 的最小操作数](#5.4 将 x 减到 0 的最小操作数)
      • [5.5 水果成篮](#5.5 水果成篮)
      • [5.6 找到字符串中所有字母异位词](#5.6 找到字符串中所有字母异位词)
      • [5.7 串联所有单词的子串](#5.7 串联所有单词的子串)
      • [5.8 最小覆盖子串](#5.8 最小覆盖子串)
  • [💻结尾--- 核心连接协议](#💻结尾— 核心连接协议)

前言

深度进阶:滑动窗口算法核心秘籍

滑动窗口是一种在线性数据结构(如数组或字符串)上执行特定操作的算法优化技巧。它通过维护一个"窗口",并根据特定条件不断移动窗口的边界,从而将原本需要嵌套循环( O ( n 2 ) O(n^2) O(n2) 或 O ( n 3 ) O(n^3) O(n3))的复杂度降低到线性时间( O ( n ) O(n) O(n))

一、什么是滑动窗口?

1.1 核心机制:左右边界的律动

滑动窗口通常使用两个指针(leftright)来定义:

  1. 右边界 right 扩张:寻找可行解。不断扩大窗口,将新元素包含进来。

  2. 左边界 left 收缩:优化可行解。当窗口满足(或不再满足)某种特定条件时,收缩左侧以寻找"最优解"或使窗口重新符合规范。

滑动窗口本质上是对双指针技巧的深度优化

通过维护一组逻辑上连续的子序列(即"窗口"),在 O ( N ) O(N) O(N) 的时间复杂度内解决数组或字符串中的子区间类问题


1.2 🖼️ 滑动窗口动态演示:寻找和为 7 的连续子数组

假设数组为 [2, 3, 1, 2, 4, 3],我们要寻找和 ≥ 7 \ge 7 ≥7 的最小子数组长度

1. 窗口扩展阶段
右指针 right 向右移动,吸收新元素

Plaintext 复制代码
指针位置:  [ 2,  3,  1,  2,  4,  3 ]
            L   R                     (Window Sum = 2)
            L       R                 (Window Sum = 5)
            L           R             (Window Sum = 6)
            L               R         (Window Sum = 8) -> 触发条件!

2. 窗口收缩阶段

当条件满足时,左指针 left 向右移动,尝试压缩窗口寻找最优解

Plaintext 复制代码
指针位置:  [ 2,  3,  1,  2,  4,  3 ]
                L           R         (Window Sum = 6) -> 不满足,停止收缩



Start
Right 指针右移
是否满足窗口条件?
记录/更新当前最优解
Left 指针右移


二、滑动窗口的两大分类

根据窗口长度是否固定,我们可以将其分为两类:

2.1 固定窗口

  • 适用场景:求长度为 ( K ) 的子数组的最大和、计算固定长度的平均值等

  • 操作逻辑

    • 先初始化第一个窗口

    • 窗口整体向右平移:

      c 复制代码
      right++, left++;
    • 更新状态:

      c 复制代码
      new_sum = old_sum + nums[right] - nums[left-1];

2.2 可变窗口

窗口的宽度随条件动态变化,这是算法面试中的高频考点

  • 适用场景: 求满足条件的"最小子数组"或"最大不重复子串"

  • 操作逻辑:

    • right 主动向右移动
    • 在内部使用 while 循环判断条件,动态收缩 left

三、滑动窗口的通用模板

3.1 解题思路模板

无论是固定窗口还是变长窗口,其逻辑均可抽象为以下四部曲:

  1. 进窗 :右指针 right 主动右移,将元素纳入窗口,更新窗口状态

  2. 判断:判断当前窗口是否触发特定条件(如窗口长度达到阈值、窗口内元素重复等)

  3. 出窗 :左指针 left 被动右移,将元素移出窗口,同时恢复窗口状态

  4. 更新:在上述过程中,实时更新最终的结果(如最大长度、最小和等)


3.2 代码模板

cpp 复制代码
void slidingWindow(string s, string t) {
    unordered_map<char, int> window;
    int left = 0, right = 0;
    int valid = 0; // 记录窗口中满足条件的字符个数

    while (right < s.size()) {
        // a. c 是将移入窗口的字符
        char c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        ...

        /*** debug 输出的位置 ***/
        // printf("window: [%d, %d)\n", left, right);
        /********************/

        // b. 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}

四、滑动窗口的使用时机

当你在处理连续的序列(数组或字符串)问题,且窗口的边界需要根据特定条件动态移动时,就是滑动窗口大显身手的时候

  • 单调性滑动窗口本质上就是利用了单调性,规避很多没有必要的枚举

    当窗口向右扩大时,窗口内的某个属性(如和、计数)具有单调递增或递减的特性,这允许我们通过移动左边界来恢复复合规律

  • 线性数据结构:处理的对象是数组、字符串或链表。

  • 连续性:题目要求找的是"子数组"、"子串"或"连续区间"。(如果是子序列或不连续组合,通常考虑动态规划或回溯。)

  • 规模要求:寻找满足某种条件的最长/最短区间,或者特定长度的区间


五、滑动窗口典型算法题目

5.1 长度最小的子数组

Lucy的空间骇客裂缝:leetcode原题

5.2 无重复字符的最长子串

Lucy的空间骇客裂缝:leetcode原题

5.3 最大连续 1 的个数 III

Lucy的空间骇客裂缝:leetcode原题

5.4 将 x 减到 0 的最小操作数

Lucy的空间骇客裂缝:leetcode原题

5.5 水果成篮

Lucy的空间骇客裂缝:leetcode原题

5.6 找到字符串中所有字母异位词

Lucy的空间骇客裂缝:leetcode原题

5.7 串联所有单词的子串

Lucy的空间骇客裂缝:leetcode原题

5.8 最小覆盖子串

Lucy的空间骇客裂缝:leetcode原题


💻结尾--- 核心连接协议

警告: 🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠


【📡】 建立深度链接: 关注本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。

【⚡】 能量过载分发: 执行点赞操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。

【💾】 离线缓存核心: 将本页加入收藏。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。

【💬】 协议加密解密:评论区留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。

【🛰️】 信号频率投票: 通过投票发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。



相关推荐
徐小夕31 分钟前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei1 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld1 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi83 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
搬砖魁首4 小时前
基础能力系列 - 多线程2 - 条件变量
c++·rust·条件变量·原子类型·线程同步互斥
youngerwang4 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
chase_my_dream4 小时前
C++ + SLAM 高频面试问题整理
开发语言·c++·面试
牛油果子哥q4 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++
KaMeidebaby4 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠5 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc