算法基础集训(第22天,共106天)------>彻底弄懂【单调栈】模型

461a8ee9293542f78e46aa08946caa7d.gif

一:概念定义 

单调栈可分为:单调递增栈单调递减栈

  • 单调递增栈:单调递增栈就是从栈底到栈顶数据是从大到小
  • 单调递减栈:单调递减栈就是从栈底到栈顶数据是从小到大
  • 但是名字其实不重要,做题目只需判断存储的数据从站栈底到栈顶的单调情况即可

二:单调栈题型

一般涉及的题目为求离某个数最近的且满足某个条件的数


三:题目描述 

给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。

输入格式

第一行包含整数 N,表示数列长度。

第二行包含 N 个整数,表示整数数列。

输出格式

共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。

数据范围

 

1 ≤ N ≤ 10^5
1 ≤ 数列中元素 ≤ 10^9

输入样例

5

3 4 2 7 5

输出样例 

 -1 3 -1 2 2


四:思路解析 

朴素暴力做法: 

for (int i = 0; i < n; i ++){
    for (int j = i-1; j >=0; j --){
        if(a[i] > a[j])
        {
            cout << a[j] << endl;
            break;
        }
    }
}

显然该方法太暴力,当数据量大时就容易超时,因此我们要想方设法用到栈的特点

分析:假设我们到达了a【i】的位置,要往前寻找离a【i】最近且小于a【i】的数字,如果用上面的做法越到后面,重复检验的数字就越来越多。比如:x < y,a【x】>  a【y】,显然,对应a【i】而言,找到的数字肯定不是a【x】,答案一定是在a【y】以及a【y】的后边。如下图:7d47c1b29d73434394d94cf33f4f6e1f.png

 

 因此,很多数字其实不需要一直保留在栈内部。我们这么去思考:让栈内的元素按照一定条件的筛选之后始终保持单调递增,a【i】只需要始终和栈顶元素比较,只要栈顶元素小于a【i】说明栈顶元素符合题意,如果栈顶元素大于等于a【i】,就把栈顶弹出,和下一任栈顶比较,以此类推。观察下图就容易理解:70e1e84b47294b39beb6dd122f41fd71.gif

 简单粗暴的理解:我们在维护a【i+1】,我们就要利用a【i】,将a【i】之前(不包括a【i】)所有大于a【i】的数字全部弹出,让a【i】做栈顶元素

 注:我们容易发现,任何时候从栈底到栈顶都是递增的,但是至于是递增栈还是递减栈不重要,我们只需要在做题目的时候判断出其栈内部的排列顺序即可。


五:万年无误代码模板 

#include <iostream>
using namespace std;

const int N = 100010;
int stk[N], top;

int main()
{
    int n;
    cin >> n;
    
    while (n -- )
    {
        int x;
        scanf("%d", &x);
        while (top && stk[top] >= x) top -- ;//如果栈顶元素大于当前待入栈元素,则出栈
        if (!top) printf("-1 ");//如果栈空,则没有比该元素小的值。
        else printf("%d ", stk[top]);
        stk[ ++ top] = x;
    }
    
    return 0;
}

 创作不易,建议点赞+收藏+关注,以免找不到宝贝文章了。

基础集训结束后将开展拔高系列

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码kobe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值