单调栈——力扣84题_独行的喵的博客-程序员宅基地

技术标签: 算法  算法/力扣刷题  leetcode  职场和发展  数据结构  

单调栈

我们从力扣84题的解决思路中引出单调栈的概念,首先看力扣84题的题目描述如下:
在这里插入图片描述关于暴力解:这道题是要寻找最大的而矩形区域,暴力的解法是:以每一个柱子为基准,寻找包含该柱子的最大矩形区域。即遍历到每一个柱子时,寻找以它的高度为高,宽度最大的矩形。这样的做法十分简单,但是遍历柱子的时间复杂度是O(N),而寻找包含每一根柱子的矩形最大宽度的时间复杂度也是O(N),这样一来总的算法的时间复杂度是O(N^2)

算法的改进:能否将该问题的时间复杂度缩减到O(N)?即我们尽可能地通过一次对所有柱子的遍历来解决问题。
问题的关键还是寻找一个以第i个柱子的高度为高的矩形的最大宽度,即就是寻找一个不大于这一高度的位置索引的左界限与有界限。

关于右界限的寻找:右界限的寻找可以通过直接遍历即可,这里假设有一个栈,对于第i个柱子,我们想要寻找它的右界限,那么有两种可能,即它右边的下一个柱子高度比它小,那么下一个柱子就成了它的右界限;而如果下一个柱子的高度比他大,那么它的右界限就还是未知的。直到,碰到遍历到一个高度比它小的柱子,那么这个柱子的位置就成了它的右界限。

  • 右边界的寻找过程可以具化成一个栈的操作:即当栈空时,遍历到的柱子入栈,当下一个遍历到的柱子比栈顶柱子高时,此时没有任何柱子的右边界可以确定,所以继续入栈;当遍历到的柱子比栈顶柱子低时,那么此时栈顶柱子的右边界就被确定了。将栈顶元素出栈计算宽度,然后再看新的栈顶元素会不会因为刚才这个遍历到的柱子的出现而被确定右边界,即比较新栈顶柱子和遍历到的柱子的高度,重复上述操作。

关于左界限的寻找:左界限可以是一种累计,即之前比它大的元素都可以被累计到左边界的长度中,也可以是一种记录,记录左边比它小的数的位置。基于上述栈的操作,如果要记录左边第一个比它小的柱子的位置,分两种情况,如果它不是栈中最后一个元素,那么它下面压着的那个比它小的元素的位置就是它的左界限,如果它已经是栈中最后一个元素了,说明前面的元素全部都比它大,已在它前面全部出栈了,所以它的左界限可以延伸到数组最前面。

单调栈的概念:首先单调栈是一种栈类型的数据结构,拥有栈所拥有的一切基本操作。单调栈的特殊之处在于它符合这样的特性:栈中的元素从栈底到栈顶的排列顺序是单调有序的,如果从栈底到栈顶,元素单调递减,我们称之为递增栈,因为在出栈时,元素的顺序是递增的;而如果从栈底到栈顶元素是递增的,那么称之为递减栈。
单调栈在入栈时必须保持单调性,如果将要入栈的元素不符合单调性,那么我们将栈顶元素弹出,直到让入栈元素入栈后可以符合单调性为止。以单调递减栈为例,加入入栈元素依次为1 2 5 4,那么前三个元素1 2 5 可以直接入栈,但是当元素4将要入栈时,会发现栈顶元素5大于入栈元素4,所以我们要先将5出栈,然后发现此时的新栈顶元素2小于4,则此时可以入栈。

int stack[1000000];
int top=0;
void push(int index)
{
    
  stack[top++]=index;
}

int Pop()
{
    
    return stack[--top];
}

int Top()
{
    
    return stack[top-1];
}

int isEmpty()
{
    
    if(top==0)
    return 1;
    else return 0;
}

int largestRectangleArea(int* heights, int heightsSize){
    
    int i=0,max=0,temp=0,pre=0;
    while(i<heightsSize)
    {
    
    if(isEmpty()||heights[Top()]<=heights[i])
    {
    
        push(i++);
    }
    else{
    
        if(top==1)
        {
    
         temp=i*heights[Pop()];
         if(max<temp) max=temp;
        }
        else{
    
          temp=(i-stack[top-2]-1)*heights[Pop()];
         if(max<temp) max=temp;
        }
    }
    }
    while(!isEmpty())
    {
    
        if(top==1)
        {
    
         temp=i*heights[Pop()];
         if(max<temp) max=temp;
        }
        else{
    
          temp=(i-stack[top-2]-1)*heights[Pop()];
         if(max<temp) max=temp;
        }
    }
    return max;  
}

有了以上的分析,基于单调栈的算法实现就很简单了。
我们挨个遍历数组中的元素,如果栈空或者不小于栈顶元素就入栈,否则将栈顶元素出栈,出栈的同时计算基于该柱子的矩形面积,即左右界限之间形成的宽度与该矩形的高度相乘。(在计算左右界限间宽度时要加以判断,看出栈的元素是否为栈底元素)
当遍历结束后,如果栈中还有元素,则依次出栈计算面积,最终将结果更新为最大面积即可。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45863060/article/details/121949217

智能推荐

【Java基础】· 常用类习题详解_java关于类的编程题_麟-小白的博客-程序员宅基地

Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!!!如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多呀!爱你们!!!目录【往期回顾】判断输出结果String str1 = "尚硅谷";String str2 = "尚硅谷";String str3 = new String("尚硅谷");//true。

计算机取证volatility_R0be1l的博客-程序员宅基地

带有恶意软件的内存镜像下载:https://github.com/volatilityfoundation/volatility/wiki/Memory-SamplesDumpIt v1.3.2:https://qpdownload.com/dumpit/一、volatility v2.61.使用内存镜像转储工具dumpit生成内存镜像文件(.raw)或者使用虚拟机快照文件(.vmem...

Django 中数据库的相关操作_zero.....的博客-程序员宅基地

本节内容路由系统 models模型 admin views视图 template模板引子讲django的models之前, 先来想一想, 让你通过django操作数据库,你怎么做? 做苦思冥想,可能会这样写。 1 2 3 4 5 6 7 8 9 10 11 12...

spring data redis RedisTemplate操作redis相关用法(转载)_org.springframework.data.redis.core.redistemplate _从心归零的博客-程序员宅基地

https://www.cnblogs.com/jifeng/p/4676863.html写得很全面,根本无需补充http://blog.mkfree.com/posts/515835d1975a30cc561dc35dspring-data-redis API:http://docs.spring.io/spring-data/redis/docs/1.5.1.RELEASE/api/首先跟大家...

错误笔记_apk is neither a directory nor file (type=1)._浪子哥学习笔记的博客-程序员宅基地

一、django + celery 报错: File "D:\python3.6\lib\site-packages\djcelery\management\commands\celery.py",line 23, in Command preload_options)TypeError: can only concatenate list (not "tuple") to list...

随便推点

凸优化简介25_随机镜像下降_qq_36573282的博客-程序员宅基地

文章目录随机梯度下降的下界与性能提升1. 随机梯度下降的下界2. 随机镜像下降(Stochastic Mirror Descent)3. 随机梯度下降的提升3.1 Reduce Variance3.2 自适应步长3.3 自适应 Bregman Distance随机梯度下降的下界与性能提升1. 随机梯度下降的下界考虑一个一维空间上的函数 f(x)=E[12(x−ξ)2]f(x)=\mathbb...

oracle中的exists 和not exists 用法详解_Ash_SeaShore的博客-程序员宅基地

有两个简单例子,以说明 “exists”和“in”的效率问题1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ;    T1数据量小而T2数据量非常大时,T12) select * from T1 where T1.a in (select T2.a from T2) ;     T

Selinux 配置_scontext=u:r:system_app:s0 tcontext=u:object_r:apk_Brave & Real的博客-程序员宅基地

SOC: Rk3399, Platform: Android 8.0.一: 文件不可写,未获取到write属性。在打印错误log中获取主要信息 denied --&gt;需要获取的权限,name--&gt;需要获取权限的文件,scontext--&gt;需要配置的文件,tcontext--&gt;文件所在路径,tclass--&gt;文件类型。type=1400 audit(0.0:49): avc: denied { write } for name="dwc3_mode" dev="s...

洋桃开发板笔记(四) 0.96OLED显示器的使用_Mannixcsdn的博客-程序员宅基地

OLED0561 显示器的使用杜洋工作室 www.DoYoung.net洋桃电子 www.DoYoung.net/YT在此声明一下所有代码均为 杜洋工作室 的不允许复制,转发等,本人只是在此程序上进行理解和注释。上一次的笔记是在洋桃开发板上进行用usart通信,对小电灯的控制。对串口通信有兴趣可以去看看:https://blog.csdn.net/qq_40546576/arti...

iOS12.1.3~12.2可以越狱了,附iOS12.1.3~12.2越狱教程,以及下载地址_宅哥技术的博客-程序员宅基地

一位越狱开发者Pwn20wnd在昨日凌晨发布了一款 unc0ver3.3.0 beta 2的越狱工具,喜欢越狱的小伙伴快来了解一下。想要越狱的果粉们终于等到了,快来跟着我...

推荐文章

热门文章

相关标签