单调栈
给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。
输入格式
第一行包含整数 N,表示数列长度。
第二行包含 N 个整数,表示整数数列。
输出格式
共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。
数据范围
1≤N≤105
1≤数列中元素≤109
输入样例:
5
3 4 2 7 5
输出样例:
-1 3 -1 2 2
分析:
维护一个单调递增的栈,每次输入一个元素,我们都需要判断该元素是否大于栈顶元素,如果大于栈顶元素,则可直接输出栈顶元素(栈顶元素就是它左侧第一个比它小的元素)。如果元素小于栈顶元素,则一直出栈直到该元素可以入栈,如果栈内还有元素则同上,否则不存在比该数字小的数,输出-1.
代码: C++
用数组模拟栈
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,a[N],h,t=-1; //模拟栈,h表示头指针,t表示尾指针,初始为空(t为-1)
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
while(t>=h && x<=a[t]) t--; //如果栈不空且该元素小于栈顶元素,栈顶元素出栈。
if(t<h) printf("%d ",-1); //如果栈空,则没有比该元素小的数,输出-1
else printf("%d ",a[t]); //反之输出栈顶元素
a[++t]=x;
}
return 0;
}
使用 vector 容器表示栈:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,x;
vector<int> a;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x;
while(!a.empty() && x<=a.back()) a.pop_back();
if(a.empty()) printf("%d ",-1);
else printf("%d ",a.back());
a.push_back(x);
}
return 0;
}
算法比赛手动模拟会比使用容器快一点儿(开了O2或者O3优化就差不多了)。