mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
603 字
2 分钟
滑动窗口算法
2025-07-11

滑动窗口算法笔记#

什么是滑动窗口算法#

滑动窗口算法是一种常用的算法技巧,主要用于解决数组/字符串的子数组/子字符串问题。它通过维护一个窗口,在线性时间内解决一些原本需要嵌套循环的问题。

核心思想#

  • 用两个指针(left 和 right)表示窗口的左右边界
  • right 指针负责扩展窗口,left 指针负责收缩窗口
  • 通过移动指针来调整窗口大小,寻找满足条件的子数组

适用场景#

  1. 固定窗口大小:窗口大小固定,求窗口内的最大值、最小值、平均值等
  2. 可变窗口大小:根据条件动态调整窗口大小
  3. 字符串匹配:在字符串中寻找包含特定字符的子串

滑动窗口的类型#

1. 固定窗口#

public void fixedWindow(int[] nums, int k) {
for (int i = 0; i <= nums.length - k; i++) {
// 处理窗口 [i, i+k-1]
for (int j = i; j < i + k; j++) {
// 处理窗口内元素
}
}
}

2. 可变窗口(收缩型)#

public void variableWindow(int[] nums) {
int left = 0;
for (int right = 0; right < nums.length; right++) {
// 扩展窗口
// 添加 nums[right] 到窗口
while (/* 窗口需要收缩的条件 */) {
// 收缩窗口
// 移除 nums[left] 从窗口
left++;
}
// 更新结果
}
}

解题模板#

public int slidingWindow(int[] nums, int target) {
int left = 0, right = 0;
int windowSum = 0; // 窗口内元素和(根据题目调整)
int result = 初始值;
while (right < nums.length) {
// 1. 扩展窗口:将 nums[right] 加入窗口
windowSum += nums[right];
// 2. 判断窗口是否需要收缩
while (/* 收缩条件 */) {
// 3. 更新结果(在收缩前)
result = Math.min/max(result, right - left + 1);
// 4. 收缩窗口:将 nums[left] 移出窗口
windowSum -= nums[left];
left++;
}
// 5. 移动右指针
right++;
}
return result;
}

实战题目:LeetCode 209 - 长度最小的子数组#

题目描述#

给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

解题思路#

  1. 暴力解法:时间复杂度 O(n²),枚举所有子数组
  2. 滑动窗口:时间复杂度 O(n),用双指针维护窗口

代码实现#

class Solution {
public int minSubArrayLen(int target, int[] nums) {
int length = nums.length;
int left = 0; // 左指针
int result = Integer.MAX_VALUE; // 结果:最小长度
int sum = 0; // 当前窗口和
// 特殊情况处理
if (length == 0) {
return 0;
}
// 滑动窗口
for (int right = 0; right < length; right++) {
// 1. 扩展窗口:将 nums[right] 加入窗口
sum += nums[right];
// 2. 收缩窗口:当窗口和 >= target 时
while (sum >= target) {
// 3. 更新结果:记录当前窗口长度
result = Math.min(result, right - left + 1);
// 4. 收缩窗口:移除 nums[left]
sum -= nums[left];
left++;
}
}
// 5. 返回结果
return result == Integer.MAX_VALUE ? 0 : result;
}
}

算法分析#

时间复杂度:O(n)

  • 虽然有嵌套循环,但每个元素最多被访问两次(一次被 right 指针访问,一次被 left 指针访问)

空间复杂度:O(1)

  • 只使用了常数个额外变量

执行过程示例#

以 nums = [2,3,1,2,4,3], target = 7 为例:

初始: left=0, right=0, sum=0, result=∞
right=0: sum=2, sum<7, 继续扩展
right=1: sum=5, sum<7, 继续扩展
right=2: sum=6, sum<7, 继续扩展
right=3: sum=8, sum>=7, 开始收缩
result = min(∞, 3-0+1) = 4
left=0: sum=8-2=6, sum<7, 停止收缩
right=4: sum=10, sum>=7, 开始收缩
result = min(4, 4-1+1) = 4
left=1: sum=10-3=7, sum>=7, 继续收缩
result = min(4, 4-2+1) = 3
left=2: sum=7-1=6, sum<7, 停止收缩
right=5: sum=9, sum>=7, 开始收缩
result = min(3, 5-3+1) = 3
left=3: sum=9-2=7, sum>=7, 继续收缩
result = min(3, 5-4+1) = 2
left=4: sum=7-4=3, sum<7, 停止收缩
最终结果: 2

常见变形题目#

  1. LeetCode 3 - 无重复字符的最长子串
  2. LeetCode 76 - 最小覆盖子串
  3. LeetCode 438 - 找到字符串中所有字母异位词
  4. LeetCode 567 - 字符串的排列

总结#

滑动窗口算法的关键在于:

  1. 正确定义窗口的含义
  2. 明确扩展和收缩的条件
  3. 在合适的时机更新结果

掌握了滑动窗口的思想和模板,就能高效解决一大类数组和字符串问题。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

滑动窗口算法
https://xinrose.top/posts/aigo/sliding-window-algorithm-notes/
作者
xinRose
发布于
2025-07-11
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
算法中的哈希思想:从 O(N²) 到 O(N)
算法笔记 算法中的哈希思想:从 O(N²) 暴力优化至 O(N) 高效映射,深入浅出解析哈希表在经典算法中的核心思想与解题模板。
2
实习经历背诵底稿(云玑版):真实代码与面试口径对照及高频题库
项目 高校教学信息反馈平台 Java 开发实习经历完整背诵底稿:实习三问话术、慢 SQL 索引优化、EasyExcel 流式防 OOM、Semaphore 导出限流、真实代码与面试口径对照表及网申开放题回答。
3
AI PPT 智能生成平台:架构原理、核心源码与面试通关手册
项目 基于 LangChain4j + LangGraph4j + DeepSeek 的 AI PPT 智能生成平台全景剖析:结构化输出 JSON Schema、自纠工作流状态图、Redis 阻塞队列与 SSE 流式推送、Tool Calling 局部编辑、Apache POI 原生 PPTX 两阶段质检门禁,以及 PGVector RAG 检索与生成期溢出自动收缩。
4
一场小厂技术面复盘:简历钩子、八股现形与破局补漏
面试 深圳某小公司 Java 开发岗技术面复盘:项目撑场、八股暴露,总结简历钩子诱饵策略、三大短板深度补漏方案及 HR 面谈薪避坑指南。
5
在 16G 内存的笔记本上压测优惠券系统:4 万次抢券、百万行分发,我压出了 4 个生产级 Bug
项目 在 16G 笔记本上极限压测优惠券营销平台(QPS 4600+、TPS 1600+、百万分发约 15 分钟),进行全链路三方对账,排查并解决消息风暴、快照错位与 Redis SPOP 事务缺口等 4 个生产级 Bug。

目录