1.stack--栈:后进先出
取栈顶元素:top();
入栈:push();
出栈:pop();
2.queue--队列:先进先出,模拟排队过程
队首元素:front();
队尾元素:back();
删除队尾:pop();
进入队列:push();
3.deque--双端队列:
队首添加元素:push_front();
队尾添加元素:push_back();
删除队首元素:pop_front();
删除队尾元素:pop_back();
4.双端队列在单调队列中的应用:
eg:给定一个大小为 n≤1e6 的数组。
有一个大小为 k的滑动窗口,它从数组的最左边移动到最右边。
你只能在窗口中看到 k个数字。
每次滑动窗口向右移动一个位置。
以下是一个例子:
该数组为 [1 3 -1 -3 5 3 6 7]
,k为 3。
窗口位置 | 最小值 | 最大值 |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
请确定滑动窗口位于每个位置时,窗口中的最大值和最小值。
输入样例:
8 3
1 3 -1 -3 5 3 6 7
输出样例:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
//单调队列
const int maxn=1e6+5;
int a[maxn];
deque<int> q;
//队首元素存放最值下标
//维护最小值队列(递增队列)
for(int i=0;i<n;i++)
{
if(q.size()&&q.front()<i-k+1){
q.pop_front(); //判断队首元素是否超出区间长度
}
while(q.size()&&a[q.back()]>=a[i]){
q.pop_back();
}
q.push_back(i);
if(i>=k-1){
cout<<a[q.front()]<<' ';
}
}
cout<<'\n';
q.clear();
//维护最大值队列(递减队列)
for(int i=0;i<n;i++)
{
if(q.size()&&q.front()<i-k+1){
q.pop_front();
}
while(q.size()&&a[q.back()]<=a[i]){
q.pop_back();
}
q.push_back(i);
if(i>=k-1)
{
cout<<a[q.front()]<<' ';
}
}