news 2026/9/12 4:03:26

滑动窗口最大值算法:单调队列原理与Go实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
滑动窗口最大值算法:单调队列原理与Go实现

1. 问题背景与核心挑战

LeetCode 239题"滑动窗口最大值"是算法面试中的经典问题,主要考察对滑动窗口和单调队列的理解与应用。给定一个整数数组nums和一个整数k,我们需要找到每个长度为k的滑动窗口中的最大值,并返回这些最大值组成的数组。

这个问题的难点在于如何高效地维护窗口内的最大值。暴力解法的时间复杂度是O(nk),当n和k较大时性能会急剧下降。我们需要设计一个时间复杂度为O(n)的算法来解决这个问题。

2. 算法思路解析

2.1 单调队列的核心思想

单调队列是解决这个问题的关键数据结构。它能在O(1)时间内获取当前窗口的最大值,同时维护队列中的元素按照从大到小的顺序排列。这种数据结构特别适合需要频繁查询区间极值的场景。

单调队列的工作原理:

  • 队列头部始终保存当前窗口的最大值
  • 新元素入队时,从队尾开始移除所有比它小的元素
  • 窗口滑动时,检查队首元素是否已经不在当前窗口,如果是则移除

2.2 算法步骤详解

  1. 初始化一个空的双端队列和结果数组
  2. 遍历输入数组: a. 移除队列中不在当前窗口的元素(从队首) b. 移除队列中所有比当前元素小的元素(从队尾) c. 将当前元素加入队列 d. 如果窗口大小达到k,将队首元素加入结果
  3. 返回结果数组

3. Go语言实现详解

func maxSlidingWindow(nums []int, k int) []int { if len(nums) == 0 { return []int{} } var queue []int // 存储的是下标而不是值 result := make([]int, 0, len(nums)-k+1) for i := 0; i < len(nums); i++ { // 移除不在窗口内的元素 if len(queue) > && queue[0] <= i-k { queue = queue[1:] } // 移除所有比当前元素小的元素 for len(queue) > 0 && nums[queue[len(queue)-1]] < nums[i] { queue = queue[:len(queue)-1] } // 添加当前元素 queue = append(queue, i) // 当窗口形成后,添加结果 if i >= k-1 { result = append(result, nums[queue[0]]) } } return result }

3.1 代码关键点解析

  1. 队列存储的是元素下标而不是值,这样可以方便判断元素是否在窗口内
  2. 每次迭代都先检查队首元素是否还在窗口内
  3. 从队尾开始移除比当前元素小的元素,保持队列单调递减
  4. 只有当i >= k-1时才记录结果,确保窗口已形成

4. 复杂度分析与优化

4.1 时间复杂度

每个元素最多入队和出队一次,因此时间复杂度是O(n)。相比暴力解法的O(nk)有了显著提升。

4.2 空间复杂度

最坏情况下队列中会存储k个元素,因此空间复杂度是O(k)。

4.3 可能的优化方向

  1. 预分配结果数组大小避免多次扩容
  2. 对于特定数据分布(如部分有序),可以进一步优化
  3. 并行化处理大数组(需要额外考虑同步问题)

5. 实际应用场景

滑动窗口最大值算法在实际中有广泛应用:

  1. 网络流量监控:统计固定时间窗口内的最大流量
  2. 股票分析:计算特定时间段内的最高股价
  3. 信号处理:提取滑动窗口内的峰值信号
  4. 图像处理:局部最大值滤波

6. 常见问题与调试技巧

6.1 常见错误

  1. 忘记处理空输入的情况
  2. 窗口大小k大于数组长度时未正确处理
  3. 队列中存储值而非下标,导致无法判断元素是否在窗口内
  4. 边界条件处理不当(如k=1或k=len(nums))

6.2 调试建议

  1. 打印每次迭代后的队列状态
  2. 使用小规模测试用例手动验证
  3. 特别注意窗口刚开始形成和结束时的边界情况
  4. 比较暴力解法和优化解法的结果是否一致

7. 扩展思考

7.1 滑动窗口最小值

类似思路可以解决滑动窗口最小值问题,只需将单调队列改为单调递增即可。

7.2 多维滑动窗口

对于二维数组,可以扩展该算法处理二维滑动窗口的最大值问题。

7.3 动态窗口大小

当窗口大小k不是固定值时,算法需要相应调整以适应动态窗口需求。

提示:在实际面试中,除了写出正确代码外,能够清晰解释算法思路和复杂度分析同样重要。建议在练习时养成边写代码边解释的习惯。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 4:03:05

双有源桥DAB Simulink闭环仿真建模与PI参数整定实战指南

做高频隔离型DCDC的同行应该都有这种感觉&#xff1a;双有源桥&#xff08;DAB&#xff09;看着就八个管子加一个变压器&#xff0c;原理图简单到让人放松警惕&#xff0c;真正自己搭Simulink模型做闭环控制的时候&#xff0c;问题一个接一个。最近这个月我已经帮三个人远程看D…

作者头像 李华
网站建设 2026/9/12 4:01:57

text-to-cad实战指南:从自然语言到参数化模型的工程落地

text-to-cad最近在设计和制造圈子里热度很高&#xff0c;甚至不少非CAD背景的产品经理也在问&#xff0c;能不能直接说一句“给我一个带四个安装孔的矩形底座”就拿到STEP文件。我在这个方向摸了一段时间&#xff0c;试过从学术开源模型到商业预览版工具&#xff0c;踩了不少坑…

作者头像 李华
网站建设 2026/9/12 4:00:44

Python数据可视化:九九乘法表的热力图与矩阵分析

1. 项目概述&#xff1a;九九乘法表的数据可视化探索"25大数据 6-2 九九乘法表"这个看似简单的标题背后&#xff0c;隐藏着数据科学入门阶段最经典的训练案例。作为编程初学者接触的第一个完整算法实现&#xff0c;九九乘法表承载着循环结构、格式化输出、数据关系映…

作者头像 李华
网站建设 2026/9/12 3:58:34

SpringBoot+Vue工业设备管理系统全栈开发实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华