题目描述
给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。
输入格式
第一行包含整数 N,表示数列长度。
第二行包含 N 个整数,表示整数数列。
输出格式
共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。
数据范围
1≤N≤1e5
1≤数列中元素≤1e9
输入样例:
5
3 4 2 7 5
输出样例:
-1 3 -1 2 2
首先想一下暴力做法,遍历整个数列,然后对于当前的数,从前一个数开始倒序去找第一个比当前数小的数,然后输出即可。
在这其中我们会发现一个性质,对于3 4 2 7这个数列来说,对于7,我们去找他左边第一个比他小的数,会发现首先会找到2,3和4是永远不会被使用到的,因为前面有一个2是比他们小的,所以我们可以用一个栈存储已有的可能被使用到的数,如果栈顶的数比当前正在处理的数大,那么栈顶的数以后一定不会被用到(因为当前处理的数a一定是在栈顶的数b的右边且小于b,如果后面的数c往前查找比c小的数,一定是先输出a,排位上是b ... a ... c,大小关系a < b,如果b能满足条件,那么a一定满足条件,所以b不会被用到,直接弹出栈即可)。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int stk[N],tt;
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i ++ ){
int x;
cin >> x;
while(tt && x <= stk[tt])tt --;//查找比当前数小的,如果栈顶比当前处理的数x大的直接弹出栈即可,因为以后也不会被用到。
if(tt)cout << stk[tt] << ' ';//栈不空那么输出栈顶,栈顶此时是比当前数小的第一个数。
else cout << -1 << ' ';//栈空输出 -1,说明没有比当前处理的数小的。
stk[++ tt] = x;//每次别忘了把x压入栈里
}
return 0;
}