数据结构——单调栈

前导:

        队列,前面的链接是对普通的栈,和普通的队列的一个讲解,如果没有对普通的栈和队列不了解的小伙伴可以先看看前面链接中的讲解;

        什么是单调,一个序列呈递增或者递减,并且没有一个位置违反了这个递增递减的性质,那么这个序列就算单调序列;

单调栈

        咱么先讲单调栈,什么是单调栈,知名知其意,栈里面的元素应该是单调的;而单调栈的作用就是去维护它里面的元素成单调性,例如它可以用来找某个元素左右侧最近比他大比他小的元素的位置;下面直接来图片演示他是如何操作的:

       初始状态       开始入栈:

        一直入栈直到索引3时: 

        现在继续入栈,到索引5,如果直接入栈索引5又破坏了单调性,那么又需要出栈元素:

        最后通过,这样的操作之后,最终结果为:

单调栈的作用

       单调栈的主要作用是在处理数据序列中,帮助快速解决一些需要维护单调性的问题,例如:
        1. 寻找下一个更大元素或更小元素:单调栈可以用于查找某个元素右侧或左侧的第一个比它大或小的元素,这在解决一些问题中非常有用,比如上图中索引2位置的92右边最近比他小的就是索引3的65;

        2.解决其他需要维护单调性的问题:除了上述示例,单调栈还可用于解决其他需要维护单调性的问题,如找到数组中连续子数组的最大或最小值。

        等等,这些需要思考问题的过程中来进行转换,而不是死记硬背,这个就像数学一样,你背下了公式,但是你也不一定会做题,所以需要多做题进行来加深自己的逻辑框架。

例题:

        这个数据结构直接去实现没有太大的作用,所以选择一个题目进行来讲解:

        leetcode 84

        让你求最大矩形的面积,而这个问题就是进行枚举,然后求每一个矩形的面积,而求每一个矩形的面积如何求,那么这里就可以用到单调栈;

        如何求该位置的面积:

        

        初始化,单调栈:

        然后可能会有疑问,觉得现在还是没有头绪,没关系往后看:

        然后继续上面的操作:

        而从数组右边开始,就是这样:

        同样的维护单调栈的性质,和左边遍历数组的操作一样,我就不画图了;

        然后一直进行这样维护单调栈的性质,最终得到结果:

        然后通过两个数组得到,每个位置可以得到的最大的矩形面积,然后再枚举一次数组,进行得到最终最大矩形面积:

        

        

        最终找到题目要求的答案;

int largestRectangleArea(int* heights, int heightsSize){
    int n = heightsSize;
    int l[n + 5], r[n + 5];//创建l,r数组
    int s[n + 5];//创建栈
    memset(s, 0, sizeof(s));//初始化清空栈
    int top = -1;//top = 0,-1都可以,只是有些条件需要变化一下,这是不影响的
    s[++top] = -1;//入栈虚拟位置
    for (int i = 0; i < n; i++) {
        while (top > 0 && heights[s[top]] >= heights[i]) top--;//top > 0,虚拟位置一直存在栈中,就不用再创建新数组来添加虚拟位置,相当于虚拟位置的高度-1在心中
        l[i] = s[top]; //将最近做左边比i位置高度矮的最近位置记录下来
        s[++top] = i; //入栈i,现在的栈已经维护到入栈i位置一样成单调递增
    }
    top = -1;//初始化栈顶指针
    s[++top] = n;//将虚拟位置入栈
    for (int i = n - 1; i >= 0; i--) {//和上面的逻辑一样,就不解释了
        while (top > 0  && heights[s[top]] >= heights[i]) top--;
        r[i] = s[top];
        s[++top] = i;
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        int sum = heights[i] * (r[i] - l[i] - 1);//枚举找每个位置的最大面积
        ans = fmax(sum, ans);//记录最大矩形面积
    }
    return ans;
}

 单调队列明天会出文章续上,这篇已经花了4个小时了,觉得有用给作者一个赞吧;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

初猿°

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

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

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

打赏作者

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

抵扣说明:

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

余额充值