单调队列
单调队列
主要题型
求滑动窗口之中的最大值或最小值
暴力做法
通过两侧循环来遍历数组,第二层循环模拟滑动窗口,通过比较记录最大值(最小值)
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 3 -1 -3 5 3 6 7)
题目
题目链接
滑动窗口:https://www.acwing.com/problem/content/156/
AC代码
学代码就上AcWing!!!
#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;
}