当前位置: 首页 > news >正文

单调队列-滑动窗口算法一篇学会-AcWing 154. 滑动窗口

滑动窗口题解

题目传送门:
AcWing 154. 滑动窗口

题目描述

给定一个大小为 n ≤ 10^6 的数组和一个大小为 k 的滑动窗口,窗口从数组最左端移动到最右端。要求输出窗口在每个位置时的最小值和最大值。

样例解释
输入数组为 [1 3 -1 -3 5 3 6 7],k=3
输出:
最小值序列:-1 -3 -3 -3 3 3
最大值序列:3 3 5 5 6 7

题目分析

这是一个典型的滑动窗口问题,需要在O(n)时间复杂度内解决。直接暴力求解对于每个窗口遍历k个元素的话,时间复杂度会是O(nk),对于n=1e6来说不可接受。

解题思路

使用单调队列来优化:

  1. 最小值:维护一个单调递增队列,队首元素即为当前窗口最小值
  2. 最大值:维护一个单调递减队列,队首元素即为当前窗口最大值

算法讲解

  1. 队列中存储的是数组元素的下标而非值本身,这样可以方便判断元素是否在窗口内
  2. 每次移动窗口时:
    • 先检查队首元素是否还在窗口内,不在则弹出
    • 然后从队尾开始,删除所有不满足单调性的元素
    • 最后将当前元素加入队列
  3. 当窗口形成后(i≥k时),输出队首元素

代码实现

#include <bits/stdc++.h>
using namespace std;
// #define int long long
const int N = 1e6 + 10;
int n, k;
int a[N];
int q[N];  // 队列存的是下标

void solve()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    
    // 找每个窗口的最小值
    int tt = -1, hh = 0;  // 初始化队列
    for (int i = 1; i <= n; i++)
    {
        // 维护队列中的元素在窗口范围内
        while (hh <= tt && i - k + 1 > q[hh])  // 队首元素不在窗口内
            hh++;
        // 维护单调递增队列
        while (hh <= tt && a[q[tt]] >= a[i])  // 队尾元素大于等于当前元素
            tt--;  
        q[++tt] = i;  // 将当前元素下标加入队列
        
        if (i >= k)  // 窗口形成后才输出
            cout << a[q[hh]] << " ";
    }
    cout << "\n";
    
    // 找每个窗口的最大值
    tt = -1, hh = 0;  // 重置队列
    for (int i = 1; i <= n; i++)
    {
        // 维护队列中的元素在窗口范围内
        while (hh <= tt && i - k + 1 > q[hh])
            hh++;
        // 维护单调递减队列
        while (hh <= tt && a[q[tt]] <= a[i])
            tt--;
        q[++tt] = i;
        
        if (i >= k)
            cout << a[q[hh]] << " ";
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    solve();
    return 0;
}

重点细节

  1. 队列存储的是下标:这样可以方便判断元素是否还在窗口内
  2. 双条件while循环
    • 第一个while保证队首元素在窗口内
    • 第二个while维护队列的单调性
  3. 窗口形成条件:只有当i≥k时才输出结果
  4. 队列初始化:每次处理前需要重置队列指针

复杂度分析

  • 时间复杂度:O(n),每个元素最多入队和出队一次
  • 空间复杂度:O(n),用于存储队列

总结

单调队列是解决滑动窗口极值问题的高效方法,关键在于:

  1. 维护队列的单调性
  2. 及时移除不在窗口内的元素
  3. 理解队列中存储下标而非值的好处

本题的经典解法值得熟练掌握,类似的滑动窗口问题都可以考虑使用单调队列优化。

相关文章:

  • js中的document.querySelect()
  • 哈希表 - 两数之和(Map) - JS
  • OpenBMC:BmcWeb 处理http请求2 查找路由对象
  • 0102-web架构网站搭建-基础入门-网络安全
  • 我的世界1.20.1进阶模组开发教程——升级模板与文字格式
  • Nginx 配置 HTTPS 与 WSS 完整指南
  • 亚马逊新卖家破局指南:从0到1搭建可持续出单模型
  • Linux内核编程
  • 关于CodeJava的学习笔记——11
  • 贪心算法(13)(java)合并区间
  • vscode 使用vue3
  • Linux内核设计——(一)进程管理
  • 2025年汽车加气站操作工备考题库
  • 基于超分辨率与YOLO的多尺度红外小目标检测方法YOLO-MST论文解读
  • OpenCV 图形API(3)高层次设计概览
  • 变量(Variable)
  • 详解VAE损失函数
  • 从零开始学Rust:所有权(Ownership)机制精要
  • Android版本更新服务通知下载实现
  • C++编程指南31 - 除非绝对必要,否则不要使用无锁编程
  • 长治做网站哪家好/软文广告例子
  • 新网站建设方案ppt/自媒体平台注册下载
  • 如何做网页跳转/搜索引擎优化论文3000字
  • 温州网站建设推广/推广运营是做什么的
  • 户外做旅游网站/啦啦啦资源视频在线观看8
  • 武汉手机微信网站建设/windows优化大师官方下载