
⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///
WARNING \]: DETECTING HIGH ENERGY
**🌊 🌉 🌊 心手合一 · 水到渠成**

|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| **\>\>\> 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