单调栈入门
作者:互联网
学习单调栈的心得,以此随笔简记之。
Intro
我们由这样一个问题来引入单调栈:给定一个 N 个元素的数组,输出每一个数左边离它最近的比它小的数,没有则输出-1。
Solution
我们一下子就想出了暴力法,对于每个数都向前回溯,直到找到或者到数组头。这样的做法是 \(O(N^2)\) 的,效率比较低下。
我们来想想有什么办法可以优化:考虑这样的情况,如果 a[i] <= a[j] 且 i> j, 那么 a[j] 是不可能被作为答案的,依照这个规则,每次回溯比较时的元素应该按递增顺序排列,而且是动态变化的,那些不可能是答案的会被剔除出这个集合。我们用一个栈来保存这些可能作为答案的数。
主要步骤如下:
- 每次有一个新元素要入栈的时候,把栈中所有比它大的元素弹出。
- 输出栈顶(如果有)。
- 新元素入栈。
由于每个元素只会入栈和出栈一次,因此这个算法是 \(O(N)\) 的,效率大大提高了。
代码
#include <iostream>
#include <stack>
using namespace std;
const int N = 100010;
int a[N];
int main(){
int n;
cin>>n;
stack<int> stk;
for(int i = 0 ; i < n ; i ++)cin>>a[i];
for(int i = 0 ; i < n ; i ++){
while(stk.size() && a[i] <= stk.top()) stk.pop();
if(stk.size()) cout<<stk.top()<<' ';
else cout<<-1<<' ';
stk.push(a[i]);
}
cout<<endl;
return 0;
}
Summary
和单调队列一样,单调栈也是一种对暴力方法的优化,它剔除了冗余操作,使得效率大大提高,主要的操作就是新元素入栈时用它剔除冗余的元素。
标签:入门,int,元素,冗余,新元素,include,单调 来源: https://www.cnblogs.com/Softwarer1412/p/14604332.html