技术标签: 算法 算法/力扣刷题 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;
}
有了以上的分析,基于单调栈的算法实现就很简单了。
我们挨个遍历数组中的元素,如果栈空或者不小于栈顶元素就入栈,否则将栈顶元素出栈,出栈的同时计算基于该柱子的矩形面积,即左右界限之间形成的宽度与该矩形的高度相乘。(在计算左右界限间宽度时要加以判断,看出栈的元素是否为栈底元素)
当遍历结束后,如果栈中还有元素,则依次出栈计算面积,最终将结果更新为最大面积即可。
碰撞检测经典解决方案
Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!!!如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多呀!爱你们!!!目录【往期回顾】判断输出结果String str1 = "尚硅谷";String str2 = "尚硅谷";String str3 = new String("尚硅谷");//true。
带有恶意软件的内存镜像下载:https://github.com/volatilityfoundation/volatility/wiki/Memory-SamplesDumpIt v1.3.2:https://qpdownload.com/dumpit/一、volatility v2.61.使用内存镜像转储工具dumpit生成内存镜像文件(.raw)或者使用虚拟机快照文件(.vmem...
本节内容路由系统 models模型 admin views视图 template模板引子讲django的models之前, 先来想一想, 让你通过django操作数据库,你怎么做? 做苦思冥想,可能会这样写。 1 2 3 4 5 6 7 8 9 10 11 12...
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/首先跟大家...
一、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...
文章目录随机梯度下降的下界与性能提升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...
有两个简单例子,以说明 “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
SOC: Rk3399, Platform: Android 8.0.一: 文件不可写,未获取到write属性。在打印错误log中获取主要信息 denied -->需要获取的权限,name-->需要获取权限的文件,scontext-->需要配置的文件,tcontext-->文件所在路径,tclass-->文件类型。type=1400 audit(0.0:49): avc: denied { write } for name="dwc3_mode" dev="s...
OLED0561 显示器的使用杜洋工作室 www.DoYoung.net洋桃电子 www.DoYoung.net/YT在此声明一下所有代码均为 杜洋工作室 的不允许复制,转发等,本人只是在此程序上进行理解和注释。上一次的笔记是在洋桃开发板上进行用usart通信,对小电灯的控制。对串口通信有兴趣可以去看看:https://blog.csdn.net/qq_40546576/arti...
多元线性回归-python代码
一位越狱开发者Pwn20wnd在昨日凌晨发布了一款 unc0ver3.3.0 beta 2的越狱工具,喜欢越狱的小伙伴快来了解一下。想要越狱的果粉们终于等到了,快来跟着我...