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

滑动窗口最大值是数组类问题中的经典难题,本文将带你用单调队列实现时间复杂度 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 小时前
Cyber骇客的逻辑节点美学 ——【初阶数据结构与算法】二叉树
c语言·数据结构·c++·链表·排序算法
課代表2 小时前
从初等数学到高等数学
算法·微积分·函数·极限·导数·积分·方程
ullio2 小时前
arc206d - LIS ∩ LDS
算法
等等小何3 小时前
leetcode1593拆分字符串使唯一子字符串数目最大
算法
量子炒饭大师3 小时前
Cyber骇客神经塔尖协议 ——【初阶数据结构与算法】堆
c语言·数据结构·c++·二叉树·github·
XLYcmy3 小时前
TarGuessIRefined密码生成器详细分析
开发语言·数据结构·python·网络安全·数据安全·源代码·口令安全
王老师青少年编程3 小时前
2025年12月GESP(C++二级): 环保能量球
c++·算法·gesp·csp·信奥赛·二级·环保能量球
KingRumn3 小时前
DBUS源码剖析之DBusMessage数据结构
linux·服务器·数据结构
weixin_433417674 小时前
Canny边缘检测算法原理与实现
python·opencv·算法