定义
- 单调栈定义:单调栈的本质还是一个栈,具备栈的性质,只不过在栈的基础上有添加了一个性质,单调栈内的元素都是有序的(升序或降序);
- 单调队列定义:单调队列使用的是双端队列,双端队列在队列的两端都可以插入和删除元素,在双端队列的基础上有添加了一个性质,单调队列内的元素都是有序的(升序或降序);
单调栈的应用
- 寻找数组中每个数左边第一个比它小的数,使用单调递增栈;
- 寻找数组中每个数左边第一个比它大的数,使用单调递减栈;
- 寻找数组中每个数右边第一个比它小的数,使用单调递增栈;
- 寻找数组中每个数右边第一个比它大的数,使用单调递减栈;
代码
寻找每个数左边第一个比他小的数,使用单调递增的栈;
int a[N];
stack<int> sta;
for(int i=0;i<n;i++)
{
while(!sta.empty()&&sta.top()>=a[i])//由于需要单调递增,所以需要判断
{ //当前元素比栈顶元素小,需要出栈。
sta.pop();
}
if(sta.empty()) cout<<-1<<" ";
else cout<<sta.top()<<" ";//当所有比当前元素大的所有栈顶元素全部出栈后,
//栈顶元素就是答案
sta.push(a[i]);
}
单调队列的应用
- 求数组中每个长度为k区间的最小值或最大值;
- 求最小值使用单调递增序列;求最大值使用单调递减序列。
代码
求数组中每个长度为k区间的最小值
int a[N];
deque<int> q;//保存元素的下标
for(int i=0;i<n;i++)
{
if(i-q.front()>=k) q.pop_front(); //判断队头元素的位置和当前位置差距是否小于k
while(!q.empty()&&a[q.back()]>=a[i]) q.pop_back();//如果队尾元素大于当前元素 则出队列。
q.push_back(i);
if(i>=k-1) cout<<a[q.front()]<<" ";//如果区间元素大于k个,开始输出。
}