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

⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///


WARNING \]: DETECTING HIGH ENERGY **🌊 🌉 🌊 心手合一 · 水到渠成** ![分隔符](https://i-blog.csdnimg.cn/direct/60a3de2294e9439abad47378e657b337.gif) |------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | **\>\>\> ACCESS TERMINAL \<\<\<** || | [**\[ 🦾 作者主页 \]**](https://blog.csdn.net/fengtinghuqu520?spm=1000.2115.3001.5343) | [**\[ 🔥 C++初阶 \]**](https://blog.csdn.net/fengtinghuqu520/category_13085789.html) | | [**\[ 💾C++进阶 \]**](https://blog.csdn.net/fengtinghuqu520/category_13085793.html) | [**\[ 📡 代码仓库 \]**](https://blog.csdn.net/fengtinghuqu520/article/details/147275999?spm=1001.2014.3001.5502) | --------------------------------------- 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 核心机制:左右边界的律动 滑动窗口通常使用两个指针(`left` 和 `right`)来定义: 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 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原题](https://leetcode.cn/problems/minimum-size-subarray-sum/) #### 5.2 无重复字符的最长子串 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/longest-substring-without-repeating-characters/) #### 5.3 最大连续 1 的个数 III > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/max-consecutive-ones-iii/) #### 5.4 将 x 减到 0 的最小操作数 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/) #### 5.5 水果成篮 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/fruit-into-baskets/) #### 5.6 找到字符串中所有字母异位词 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/find-all-anagrams-in-a-string/) #### 5.7 串联所有单词的子串 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/substring-with-concatenation-of-all-words/) #### 5.8 最小覆盖子串 > [Lucy的空间骇客裂缝:leetcode原题](https://leetcode.cn/problems/minimum-window-substring/) *** ** * ** *** ## 💻结尾--- 核心连接协议 **警告:** 🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠 *** ** * ** *** **【📡】 建立深度链接:** **关注**本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。 **【⚡】 能量过载分发:** 执行**点赞**操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。 **【💾】 离线缓存核心:** 将本页加入**收藏**。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。 **【💬】 协议加密解密:** 在**评论区**留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。 **【🛰️】 信号频率投票:** 通过**投票**发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。 *** ** * ** *** ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/57b03915c54b43a7a03fa92dbbfe57c3.gif) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0905dc972de8414bb602715de3f866ee.gif)

相关推荐
郝学胜-神的一滴11 小时前
中级OpenGL教程 006:高光反射原理与 Shader 实现
c++·unity·godot·图形渲染·three.js·opengl·unreal
玖釉-11 小时前
C++ 中的 buckets 详解:从哈希桶到 unordered_map 底层原理
算法·哈希算法·散列表
计算机安禾11 小时前
【c++面向对象编程】第35篇:构造函数与异常:如何避免资源泄露?
开发语言·javascript·c++·算法·性能优化
桀人11 小时前
类和对象——下
开发语言·c++
z2005093011 小时前
今日算法(二叉树剪枝)
数据结构·c++·算法·剪枝
雪度娃娃11 小时前
Asio异步读写——简单服务器和客户端异步通信
运维·服务器·网络·c++·php
IronMurphy11 小时前
【算法四十八】416. 分割等和子集
算法
WYH28712 小时前
C语言结构体变量和结构体指针详解:定义、访问、传参与易错点总结
c语言·开发语言·算法
我不是懒洋洋12 小时前
从零实现Transformer:从注意力机制到ChatGPT
c语言·数据结构·c++·经验分享