数据结构基础 之 单调队列_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
推荐阅读