WHCSRL 技术网

数据结构基础 之 单调队列_AKA

单调队列

主要题型

求滑动窗口之中的最大值或最小值

暴力做法

通过两侧循环来遍历数组,第二层循环模拟滑动窗口,通过比较记录最大值(最小值)

int mx = -INF;
for(int i = 0; i < n; i ++ ){
    for(int j = i; j < i + 3; j ++ ){
        mx = max(a[j], mx);
    }
    cout << mx << " ";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

算法思想

用队列模拟窗口过程,在当前队列之中,如果左侧的数据大于右边的数组,则弹出左边的数据,保证最后得到的为一个严格递增的序列,结果就是队头元素

图解:(例如:1 3 -1 -3 5 3 6 7)
在这里插入图片描述

题目

题目链接

滑动窗口:https://www.acwing.com/problem/content/156/

AC代码

学代码就上AcWing!!!
  • 1
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e6 + 10;

int n, k;
int a[N],q[N];

int main()
{
    cin >> n >> k;
    for(int i = 0; i < n; i ++ )
        cin >> a[i];
        
    int hh = 0, tt = -1;
    for(int i = 0; i < n; i ++ )
    {
    	// 队头后移
        if(hh <= tt && i - k + 1 > q[hh]) hh ++;

		// 判断当前的数据和当前尾的数据的大小,最后保证队列为一个单调队列
        while(hh <= tt && a[q[tt]] > a[i]) -- tt;
        
        q[ ++tt ] = i;

		// 保证数据有 k 个以上才可以输出
        if (i + 1 >= k) cout << a[q[hh]] << " ";
    }
    cout << endl;

	// 处理最大值,与最小值相似
    hh = 0, tt = -1;	
    for(int i = 0; i < n; i ++ )
    {
        if(hh <= tt && i - k + 1 > q[hh]) hh ++;
        while(hh <= tt && a[q[tt]] < a[i]) -- tt;
        
        q[ ++tt ] = i;
        if (i + 1 >= k) cout << a[q[hh]] << " ";
    }
    cout << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
推荐阅读