• 单调栈---基础数据结构与算法


    简介

    栈 (stack) 又名堆栈,是一种数据结构,向一个栈插入新元素又称作进栈、入栈或压栈,从一个栈删除元素又称作出栈或退栈。

    栈是一种只允许在表尾进行插入和删除操作的线性表,也就是我们所说的后进先出,我们把栈想象成往一个有底的桶中放铁饼,你从桶中拿铁饼,只能拿到最上边的,放铁饼也只能在最上边开始放,如图

    栈的实现分两种,数组模拟和链表实现,这里用数组模拟

    栈的数组模拟

    如果学过了链表,那就对栈的实现很容易上手,甚至只需要看一眼就能够领悟。

    1. const int N =100010;
    2. int stk[N],tt; //tt是栈顶的下标
    3. //栈的插入操作 下标从1开始被使用
    4. stk[++tt] = x ;
    5. //栈的弹出操作
    6. --tt;
    7. //判断栈是否为空
    8. if(tt>0) not empty //不为空
    9. else empty //为空
    10. //取栈顶元素
    11. stk[tt];

     这里大概了解了栈,那单调栈只不过是栈内元素呈单调性的栈,可能是单调递增,也可能是单调递减。

    栈的主要应用场景:找出一个序列中每个数左/右边离它最近的比它大/小的数。

    这里来一道题目,快速上手>

    题目

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

    输入格式
    第一行包含整数 N,表示数列长度。
    第二行包含 N 个整数,表示整数数列。

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

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

    输入样例:
     

    1. 5
    2. 3 4 2 7 5

    输出样例:
     

    -1 3 -1 2 2

    输出解释:

    3的左边没有比它小的数 输出-1

    4的左边比它小的数是3 输出3

    2的左边没有比它小的数 输出-1

    7的左边比它小的数并且最近的是2 输出2

    5的左边比它小的数并且最近的是2 输出2

    暴力解法

    我们首先想到的暴力算法是,我们要求第 i 个数左边比它小的数并且离它最近,那就是从 i-1 个数开始,向左边遍历,直到找到。

    那代码应该这么写

    1. for(int i = 0 ; i < n ; i++ )
    2. {
    3. for( int j = i - 1 ; j >= 0 ; j-- )
    4. {
    5. if( a[j] <= a[i] )
    6. {
    7. printf("%d ",a[j]);
    8. break;
    9. }
    10. }
    11. //
    12. }

    我们观察,暴力做法中可以有什么性质可以减少步骤?

    如果有一个数的左边某个数 x 比它还大,那么在这题中 这个x永远都不会被考虑到

    例如 a[x]  >=  a[y] 并且 x< y 那么 a[x] 就可以被删去,如图

    图中存在这样逆序的点,当我们将所有逆序的点删除了,就得到了

    这时,我们只需要将我们的 a[i] 依次与 stk[4]、stk[3]、stk[2] 、stk[1]进行比较(找到小于a[i]的)就可以得出答案

    好,这里看代码领悟一下

    单调栈解法

    1. #include <iostream>
    2. using namespace std;
    3. const int N = 100010;
    4. int stk[N], tt ;
    5. int main()
    6. {
    7. int n;
    8. scanf("%d", &n);
    9. while (n--)
    10. {
    11. int x;
    12. scanf("%d", &x);
    13. while (tt && stk[tt] >= x) tt--; //当栈中存在元素并且栈顶元素大于等于x时,从栈中弹出栈顶元素
    14. if (tt) printf("%d ", stk[tt]);//当存在栈顶元素小于x时,将此栈顶元素输出
    15. else printf("-1 "); //当未在栈中查找到小于x的元素时,栈中所有元素均被弹出,此时栈为空,输出-1
    16. stk[++tt] = x; //将x插入到栈顶
    17. }
    18. return 0;
    19. }
  • 相关阅读:
    基于keras的疫情预测模型的设计与实现
    Python-Websocket的介绍及使用方法
    人工智能的发展史
    给自己的hexo博客个性化Volantis主题
    算法-动态规划-最长递增子序列
    2022-回归日-蔚来已来秋招笔试
    Docker部署系列之Docker Compose安装Redis三主三从集群
    ps滤镜插件怎么安装上去,ps神经网络滤镜安装包
    对自动化测试的一些展望与理解
    WINUI——Trigger(触发器)使用小结
  • 原文地址:https://blog.csdn.net/qq_66805048/article/details/133552207