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

滑动窗口最大值是数组类问题中的经典难题,本文将带你用单调队列实现时间复杂度 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,ans2 = nums4 = 5。

六、复杂度分析

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

七、总结

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

相关推荐
GuWenyue31 分钟前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
我叫洋洋2 小时前
C ++ [ hello world ]
c语言·c++·算法
奋发向前wcx3 小时前
y1,y2总复习笔记5 2026.7.19
数据结构·笔记·算法
战族狼魂6 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一6 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH6 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
中达瑞和-高光谱·多光谱7 小时前
1nm到8nm光谱分辨率,你的应用该选哪款光谱相机?
算法·高光谱·高光谱相机
ChaoZiLL8 小时前
我的数据结构4-栈和队列
数据结构
香辣牛肉饭8 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
miller-tsunami8 小时前
顺序表相关知识点
数据结构·顺序表