1. 问题背景与暴力解法分析
滑动窗口最大值是LeetCode上经典的算法问题(编号239),也是面试中的高频考点。题目要求给定一个整数数组nums和窗口大小k,窗口从数组最左端滑动到最右端,返回每次窗口移动时窗口内的最大值。
最直观的暴力解法是:对于每个窗口位置,遍历窗口内的所有元素找出最大值。这种方法虽然简单直接,但时间复杂度高达O(N·K),当N和K都达到10^5量级时,计算量会达到10^10次操作,远超一般OJ系统的承受能力(通常要求10^8次操作内完成)。
注意:在算法面试中,遇到"滑动窗口"类问题,首先要考虑如何将时间复杂度优化到O(N)级别。暴力解法通常只能作为思考起点,而非最终答案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 单调队列的核心思想
2.1 数据结构选择
我们需要一种能在O(1)时间内获取当前窗口最大值的数据结构。单调队列(Monotonic Queue)完美满足这一需求——它能在维护队列元素单调性的同时,高效地进行双端操作。
单调队列的核心特性:
- 队列中的元素保持单调递减(或递增)顺序
- 新元素加入时会"淘汰"队列中比它小的元素
- 能够高效地移除超出窗口范围的旧元素
2.2 操作流程解析
以数组[1,3,-1,-3,5,3,6,7]和k=3为例:
- 初始化空队列[]
- i=0, nums[0]=1 → 队列[0]
- i=1, nums[1]=3 → 淘汰1 → 队列[1]
- i=2, nums[2]=-1 → 队列[1,2]
- 窗口形成,当前最大值nums[1]=3
- i=3, nums[3]=-3 → 队列[1,2,3]
- 最大值仍为3
- i=4, nums[4]=5 → 淘汰所有比5小的 → 队列[4]
- 最大值变为5
- i=5, nums[5]=3 → 队列[4,5]
- i=6, nums[6]=6 → 淘汰所有比6小的 → 队列[6]
- i=7, nums[7]=7 → 淘汰6 → 队列[7]
最终结果为[3,3,5,5,6,7]
3. 为什么必须使用Deque
3.1 数据结构对比分析
| 操作 | std::vector | std::deque |
|------------|-------
