单调队列和单调栈有些类似,它们的用途十分有限,但由于算法巧妙优美,所以十分受面试官的青睐。
单调队列主要用在求滑动区间内最值。
例题:
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e6 + 10;
int main()
{
int n, k;
vector<int> q; // 用一个vector模拟一个队列,队列中存储的是数的下标
scanf("%d %d", &n, &k);
int arr[N];
for(int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
// 求滑动窗口中的最小值
for(int i = 0; i < n; i ++ )
{
// 如果队列最小值已经不再滑动窗口内,将其删除
if(!q.empty() && q.front() < i - k + 1)
q.erase(q.begin());
// 如果新进来的值比队列中的最小值还要小,那么将队列中大于当前值的数删除
while(!q.empty() && arr[q.back()] >= arr[i])
q.pop_back();
q.push_back(i);
if(i >= k - 1) printf("%d ", arr[q.front()]);
}
// 这个过程下来队列中的数始终保持了有序
cout<<endl;
q.clear();
// 求最大值是类似的过程
for(int i = 0; i < n; i ++ )
{
if(!q.empty() && q.front() < i - k + 1)
q.erase(q.begin());
while(!q.empty() && arr[q.back()] <= arr[i])
q.pop_back();
q.push_back(i);
if(i >= k - 1) printf("%d ", arr[q.front()]);
}
return 0;
}