前言
一枚菜鸡,跟随y总学习算法,写一些自己对一些简单算法的理解,方便自己复习时使用
一、题目
给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。
输入格式:
第一行包含整数 N,表示数列长度。
第二行包含 N 个整数,表示整数数列。
输出格式:
共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。
数据范围
1≤N≤100000
1≤数列中元素≤1e9
输入样例:
5
3 4 2 7 5
输出样例:
-1 3 -1 2 2
二、代码部分
1.思路
类似双指针算法 先考虑暴力解(两层for循环 第二层从i-1~0 从当前元素开始 从右往左遍历第一个小于x的数), 然后思考优化方向 ,考虑根据单调性作为优化。
根据题目,每次输出当前元素左边第一个比当前元素小的数 ,在栈中的元素 若ai > aj (i<j) 则ai就没有被输出的机会(此处指 从j往后的的元素)
所以根据此单调性 可以将每次输入的元素入栈 入栈前先将栈中已存在的大于当前元素的值依次出栈(由上述可知 栈中已存在的大于当前元素的值不会再被用到) 这样就可以保证栈中元素是严格的递增的 ,
代码如下:
#include<iostream>
using namespace std;
const int N=1e5 + 10;
int stk[N] ,tt=-1 ;
int main(){
int n ;
cin>>n;
while(n--){
int x ;
cin >>x ;
while (tt !=-1 && stk[tt] >= x) tt--;
if(tt==-1) cout<<"-1 ";
else cout<<stk[tt]<<" ";
stk[++tt] = x;
}
}
该处采用的是y总数组模拟栈的写法 。
2.图示
在Acwing看到一位大佬做的图示非常清楚:
总结
单调栈用来解决这种特定情况的比较多,用来寻找数列中每个数左边第一个比他小的数。