滑动窗口最大值:单调队列高效解法

滑动窗口最大值是数组类问题中的经典难题,本文将带你用单调队列实现时间复杂度 O (n) 的高效解法,彻底搞定这道题。

一、题目回顾

给定整数数组nums和窗口大小k,窗口从数组最左侧滑动到最右侧,返回每个窗口内的最大值。

示例 :输入:nums = [1,3,-1,-3,5,3,6,7], k = 3输出:[3,3,5,5,6,7]

二、为什么不用暴力法?

暴力法的思路是 "遍历每个窗口,逐个比较求最大值",但时间复杂度是 O (nk)(n 是数组长度),当 n 和 k 很大时会超时。

我们需要更高效的方法 ------单调队列,它能在 O (1) 时间内获取窗口最大值。

三、单调队列解法思路

单调队列的核心是维护一个 "单调递减" 的双端队列 ,队列中存储的是数组元素的下标(而非值),通过以下 3 个步骤保证队列的有效性:

步骤 1:右侧元素入队(维护单调性)

遍历到元素nums[i]时,从队尾弹出所有小于等于nums[i]的元素 ,再将i加入队尾。

  • 这样队列从队首到队尾是 "单调递减" 的,队首始终是当前窗口的最大值下标。

步骤 2:左侧元素出队(保证窗口范围)

计算当前窗口的左端点left = i - k + 1,如果队首下标小于left,说明队首元素已经 "滑出窗口",需要从队首弹出。

步骤 3:记录窗口最大值

left >= 0(窗口完全形成)时,队首下标对应的元素就是当前窗口的最大值,将其存入结果数组。

四、完整代码实现(C++)

cpp

复制代码
#include <vector>
#include <deque>
using namespace std;

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> ans(n - k + 1); // 结果数组长度 = 窗口数
        deque<int> q; // 双端队列,存储下标

        for (int i = 0; i < n; ++i) {
            // 1. 右侧入队:维护队列单调递减
            while (!q.empty() && nums[q.back()] <= nums[i]) {
                q.pop_back();
            }
            q.push_back(i);

            // 2. 左侧出队:移除窗口外的元素
            int left = i - k + 1;
            if (q.front() < left) {
                q.pop_front();
            }

            // 3. 记录当前窗口最大值
            if (left >= 0) {
                ans[left] = nums[q.front()];
            }
        }
        return ans;
    }
};

五、代码解析

以示例nums = [1,3,-1,-3,5,3,6,7], k=3为例:

  • i=1(元素 3):队尾弹出 1 的下标 0,队列存 1,窗口左端点left=-1(未形成窗口)。
  • i=2(元素 - 1):队尾直接加入 2,窗口左端点left=0(窗口形成),ans [0] = nums [1] = 3。
  • i=4(元素 5):队尾弹出 - 3(下标 3)、-1(下标 2)、3(下标 1),队列存 4,窗口左端点left=2,ans[2] = nums[4] = 5。

六、复杂度分析

  • 时间复杂度:O (n)。每个元素最多入队和出队各一次,总操作次数是 O (n)。
  • 空间复杂度:O (k)。队列中最多存储 k 个元素(窗口大小)。

七、总结

单调队列是解决 "滑动窗口最值" 问题的利器,核心是通过维护队列的单调性,在 O (1) 时间内获取窗口最值。掌握这个思路后,类似的问题(如滑动窗口最小值)也能举一反三。

相关推荐
永远都不秃头的程序员(互关)2 小时前
【决策树深度探索(一)】从零搭建:机器学习的“智慧之树”——决策树分类算法!
算法·决策树·机器学习
程序员-King.2 小时前
day161—动态规划—最长递增子序列(LeetCode-300)
算法·leetcode·深度优先·动态规划·递归
西柚小萌新2 小时前
【计算机视觉CV:目标检测】--3.算法原理(SPPNet、Fast R-CNN、Faster R-CNN)
算法·目标检测·计算机视觉
高频交易dragon2 小时前
Hawkes LOB Market从论文到生产
人工智能·算法·金融
历程里程碑2 小时前
Linux 2 指令(2)进阶:内置与外置命令解析
linux·运维·服务器·c语言·开发语言·数据结构·ubuntu
_OP_CHEN2 小时前
【算法基础篇】(五十)扩展中国剩余定理(EXCRT)深度精讲:突破模数互质限制
c++·算法·蓝桥杯·数论·同余方程·扩展欧几里得算法·acm/icpc
福楠2 小时前
C++ STL | set、multiset
c语言·开发语言·数据结构·c++·算法
enfpZZ小狗2 小时前
基于C++的反射机制探索
开发语言·c++·算法
炽烈小老头2 小时前
【每天学习一点算法 2026/01/22】杨辉三角
学习·算法
MicroTech20252 小时前
微算法科技(NASDAQ :MLGO)量子安全区块链:PQ-DPoL与Falcon签名的双重防御体系
科技·算法·安全