#2495. 滑动窗口 /【模板】单调队列

题目描述

有一个长为 ( n ) 的序列 ( a ),以及一个大小为 ( k ) 的窗口。现在这个窗口从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。例如:

数组是 ([1, 3, -1, -3, 5, 3, 6, 7]), ( k = 3 )。

输入格式

输入一共有两行:

第一行有两个正整数 ( n ) 和 ( k )。

第二行有 ( n ) 个整数,表示序列 ( a )。

输出格式

输出共两行:

第一行为每次窗口滑动的最小值。

第二行为每次窗口滑动的最大值。

样例

输入数据 1
8 3
1 3 -1 -3 5 3 6 7
输出数据 1
-1 -3 -3 -3 3 3
3 3 5 5 6 7

提示

数据范围:

  • 对于 50% 的数据,( 1 \leq n \leq 10^5 )
  • 对于 100% 的数据,( 1 \leq k \leq n \leq 10^6 ),( a_i \in [-2^{31}, 2^{31}) )

参考代码:双端队列实现

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

constexpr int N = 1e6 + 7;

int a[N], n, k;

int main() {
    cin >> n >> k;
    for (int i = 0; i < n; i++) cin >> a[i];

    // 存的是下标
    // 我们的dq里面一定是单调
    // 你要么活得比我长
    // 要么能力比我强
    deque<int> dq;
    for (int i = 0; i < n; i++) {
        // 当前队首的这个点还存活不 --- 窗口长度k
        // 比如我当前位置是i,窗口长度是3
        // 可以存在的点是i, i - 1, i - 2
        if (!dq.empty() && i - k + 1 > dq.front()) {
            // 比如我现在的i = 6,k = 3 --- 4 5 6三个位置的数
            // 但是你的dq.frond() = 3,你队首是位置为3的元素
            // 已经过了你的时代 --- 你该下位了
            dq.pop_front();
        }
        // 我a[i]要把我前面能力没我强,活的没我久的全部干掉
        // 队列里如果活得没有a[i]久,能力没有a[i]强,a[i]在的一天他们就永无出头之日
        while (!dq.empty() && a[i] <= a[dq.back()]) dq.pop_back();
        dq.push_back(i);
        // 可以输出当前的最小值了 --- 窗口长度至少得达到k才可以开始输出
        if (i >= k - 1) cout << a[dq.front()] << " ";
    }
    cout << "\n";
    dq.clear();
    for (int i = 0; i < n; i++) {
        // 当前队首的这个点还存活不 --- 窗口长度k
        // 比如我当前位置是i,窗口长度是3
        // 可以存在的点是i, i - 1, i - 2
        if (!dq.empty() && i - k + 1 > dq.front()) {
            // 比如我现在的i = 6,k = 3 --- 4 5 6三个位置的数
            // 但是你的dq.frond() = 3,你队首是位置为3的元素
            // 已经过了你的时代 --- 你该下位了
            dq.pop_front();
        }
        // 我a[i]要把我前面能力没我强,活的没我久的全部干掉
        // 队列里如果活得没有a[i]久,能力没有a[i]强,a[i]在的一天他们就永无出头之日
        while (!dq.empty() && a[i] >= a[dq.back()]) dq.pop_back();
        dq.push_back(i);
        // 可以输出当前的最小值了 --- 窗口长度至少得达到k才可以开始输出
        if (i >= k - 1) cout << a[dq.front()] << " ";
    }
    cout << "\n";
    return 0;
}

参考代码:手写单调队列

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

constexpr int N = 1e6 + 7;

int a[N], dq[N];

int n, k, head = 0, tail = -1;

bool isNotEmpty() { return head <= tail; }

int top() { return dq[head]; }

void pop_front() { head += 1; }

int back() { return dq[tail]; }

void pop_back() { tail -= 1; }

void push(int x) { dq[++tail] = x; }

int main() {
    cin >> n >> k;
    for (int i = 0; i < n; i++) cin >> a[i];

    for (int i = 0; i < n; i++) {
        if (isNotEmpty() && i - k + 1 > top()) pop_front();
        while (isNotEmpty() && a[back()] >= a[i]) pop_back();
        push(i);
        if (i >= k - 1) cout << a[top()] << " ";
    }
    cout << "\n";
    head = 0, tail = -1;
    for (int i = 0; i < n; i++) {
        if (isNotEmpty() && i - k + 1 > top()) pop_front();
        while (isNotEmpty() && a[back()] <= a[i]) pop_back();
        push(i);
        if (i >= k - 1) cout << a[top()] << " ";
    }
    cout << "\n";
    return 0;
}
相关推荐
卑微小文38 分钟前
2025国内网络反爬新高度:代理IP智能轮换算法揭秘
后端·算法·架构
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧2 小时前
C语言_数据结构总结7:顺序队列(循环队列)
c语言·开发语言·数据结构·算法·visualstudio·visual studio
LIUJH12332 小时前
数据结构——单调栈
开发语言·数据结构·c++·算法
2301_807449202 小时前
字符串相乘——力扣
java·算法·leetcode
---yx8989784 小时前
数字人系统源码---v10技术五大底层架构链路全局开发思路
算法·架构·数字人·数字人源码·数字人系统
xiao--xin4 小时前
LeetCode100之二叉搜索树中第K小的元素(230)--Java
java·算法·leetcode·二叉树·树的统一迭代法
路飞雪吖~4 小时前
数据结构 && 常见的排序算法
数据结构·算法·排序算法
手握风云-4 小时前
Java数据结构第二十一期:解构排序算法的艺术与科学(三)
数据结构·算法·排序算法
爱吃柠檬呀4 小时前
《C陷阱与缺陷》读书笔记(一)
c语言·开发语言·算法·《c陷阱与缺陷》·编写程序
壮志凌云4 小时前
配对样本t检验
算法