滑动窗口最大值用std::deque维护下标最稳,核心是单调递减下标队列:队首为当前窗口最大值下标,队列存索引而非值;i

滑动窗口最大值用 std::deque 维护下标最稳
直接用 std::priority_queue 或暴力遍历,要么无法及时删除过期元素,要么超时。核心是维护一个「单调递减的下标队列」:队首永远是当前窗口内最大值的下标,队列里存的是数组索引,不是值本身。
- 每次新元素进来前,从队尾开始弹出所有
nums[deque.back()] 的下标——保证队列严格递减 - 检查队首下标是否还在窗口内:
if (deque.front() <li>窗口形成后(即 <code>i >= k - 1),nums[deque.front()]就是当前窗口最大值
为什么不能只存值,必须存下标?
因为要判断队首元素是否“过期”——窗口滑动后,旧最大值可能已不在当前范围内。如果只存 nums[i] 值,根本不知道它对应哪个位置,也就无法判断该不该删。
- 存下标能同时获得值和位置信息:
nums[deque.front()]取值,deque.front()判断是否越界 - 数组有重复值时,仅靠值无法区分先后顺序,下标天然带顺序属性
-
std::deque支持 O(1) 首尾增删,比std::vector更合适
边界处理最容易漏掉的三个点
实际写的时候,这几个地方一漏就返回空结果或越界崩溃:
- 输入
k == 0或nums.empty()必须提前返回空vector,不然循环直接崩 - 窗口大小
k > nums.size()是合法输入,此时应返回空结果,不是报错 - 初始化阶段(
i )不往答案里 push,但下标仍要入队、去尾——否则第一个窗口算不准
C++11 后推荐用 emplace_back 和 front() 而非 push_back 和 [0]
效率和可读性都更好,而且避免对 deque 做随机访问误操作。
立即学习“C++免费学习笔记(深入)”;
-
deque.emplace_back(i)比deque.push_back(i)少一次拷贝 - 始终用
deque.front()和deque.back(),别用deque[0]或deque[deque.size()-1]——后者在空队列时未定义行为 - 迭代变量用
size_t i要小心:当i 且 <code>k==1时,i-1会绕成极大正数,建议统一用int i
下标管理、越界检查、空队列防御——这三块不写进循环体里,光靠“单调性”推导很容易在实测时卡住半天。










