首页 > 其他分享 >【单调栈】总结

【单调栈】总结

时间:2023-10-09 13:12:17浏览次数:32  
标签:总结 栈为 遍历 复杂度 元素 我们 单调

单调栈有什么用?

栈为容器,特性是后入先出。

经典栈的应用场景大概为:浏览器的后退按钮实现等。即:栈的一个应用场景就是状态保持。

单调栈和经典栈的区别是,栈是一股脑的存,单调栈是让栈内的元素(或者是栈内元素的对应元素)具有单调的特性。

那这个单调的特性有啥用呢?我们不考虑其他的,只考虑栈内元素和待入栈元素。

举个例子:栈内元素如果是单调递减的,[5,4,2,1]。如果我们待入栈元素是3,为了维持单调栈,我们应该让1先出栈,然后2再出栈(因为他们比3小)。然后碰到4就不能出栈了,让3入栈。

在这个处理过程中,我们就得到了下一个比3大的元素【4】。

我们更深入一些,我们不考虑如何生成单调栈。 对于某个序列来讲 [3,1,2,4,5],我们就直接告诉你,我们处理到3的时候,生成的单调栈是[5,4,2,1],待入栈元素是3. 那么这么做有什么好处呢,换句话说,我用遍历不可以吗,我为什么要用单调栈呢? 如果我要找比3大的第一个元素,我直接从3往后遍历,找到4就结束了;如果我找比1大的第一个元素,我就往后遍历,找到2就结束了;如果我想找比2大的第1个元素,我们往后找1个,找到4就结束了;如果我们想找比4大的第1个元素,我们往后找1个,找到5就结束了。 

这样实现真是短平快,又好想,很无脑。但我们这样做真的合理吗?举个极端点的例子吧。如果某个序列是[5,4,3,2,1],我们要找比每个元素大的下一个元素,对于每个元素来说,我们都要遍历到末尾才能发现压根就没有任何元素比它大。而我们用单调栈,就可以在O(n)的时间内搞定。

我们从后往前遍历(先不说为什么,先看)生成单调栈。当遍历到1时,单调栈为空,代表已经遍历过(其实没有遍历过,但为了归一化处理,我们可以认为已经遍历过)的元素中没有比1更大的元素,我们生成的单调栈为[1];遍历到2时,我们的1弹栈了(因为如果直接让2入栈,就不符合单调递减了,下同),单调栈空了,代表已经遍历过的元素中没有比2更大的元素,我们生成的单调栈为[2];遍历到3时,我们的2弹栈了,单调栈空了,代表已经遍历过的元素中没有比3更大的元素,我们生成的单调栈为[3];。。。。。。

看明白了吗,使用暴力,我们是O(n**2)的时间复杂度和O(1)的空间复杂度;使用单调栈,我们是O(n)的时间复杂度和O(1)的空间复杂度。

那么,我们凭啥能用单调栈以空间换时间呢?

还记得吗,我们说了,栈的一个应用场景就是状态保持。但,如果只用状态保持,我们只用栈不就好了吗?用什么单调栈呢。

说干就干,我们用栈试试。

如果某个序列是[5,4,3,2,1],我们从后往前遍历的话,遍历到1时,栈为空, 代表没有比1更大的值,1入栈;遍历到2时,栈不为空,我们先把栈里的东西全倒出来看看(当然,这里就是1),1没2大,所以再按顺序把它倒回去(别忘了它是栈)。。。。。

等等,好像有哪里不对。既然是这样,我何必用栈呢,我用set()存不行吗,我用列表存不行吗,我用dict存不行吗?

问对了。何必用栈呢。只用状态保持的话,我们完全没必要用栈。

还记得吗,单调栈是让栈内的元素是单调的。

再举个例子:

[5,9,4,3,1,7]

我们生成单调栈。[7],[7,1],[7,3],[7,4],[9],[9,5]

看这个单调栈,我们赋予其含义:

当生成为[7]时,我们保证在7之后,>=7的就是7.

当生成为[7, 1]时,我们保证在1之后,>=1的是1,再大的就是7

当生成为[7,3]时,我们保证在3之后,>=3的是3,再大的就是7。

 

单调栈更像是一种状态,这个状态保持了我们已经遍历过的元素的排序状态,因为它是单调的,所以它是有序的;因为它是个栈,所以它在下标上是绝对有序的。

即,单调栈做到了在下标有序(下一个)的基础上做到元素有序(更大的元素)。

标签:总结,栈为,遍历,复杂度,元素,我们,单调
From: https://www.cnblogs.com/bjfu-vth/p/17751468.html

相关文章

  • CSS常用总结
    重置样式html,body,ul,li,a,p,div{padding:0;margin:0;//设置盒模型box-sizing:border-box;//移除移动端特有的点击高亮效果-webkit-tap-highlight-color:transparent;}body{font-family:"PingFangSC","MicrosoftYaHei","Helve......
  • Docker 安装 Redis 单机&集群总结
    前言Redis是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库redis版本:redis:6.2.13作者:易墨安装单机版安装源:DockerHub默认配置文件:配置文件示例6.2运行时指定配置文件docke......
  • PHP的错误机制总结
    PHP的错误机制总结PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课。特别说明:文章的PHP版本使用5.5.32PHP的错误级别https://www.clw9335.com/rj/首先需要了解php有哪些错误。截至到php5.5,一共有16个错误级别注意:尝试下面的代码的时候请确保打开er......
  • 2023-2024-1 20231407陈原《计算机基础与程序设计》第2周学习总结
    作业信息这个作业属于哪个课程<2023-2024-1-计算机基础与程序设计>这个作业要求在哪里<2023-2024-1计算机基础与程序设计第二周作业>这个作业的目标<熟练掌握《计算机科学概论》第一章,熟悉《C语言程序设计》第一章>作业正文https://www.cnblogs.com/CCCY12345/p/......
  • 2023-2024-1 20231415 《计算机基础与程序设计》第二周学习总结
    这给个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP/这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK02这个作业的目标阅读《计算机基础与程序设计》和《C语言》并完成测试作业正文https://i.cnblogs.com/po......
  • 2023-2024学期 20231418 《计算机基础与程序设计》第2周学习总结
    2023-2024-120231418《计算机基础与程序设计》第2周学习总结作业信息这个作业属于哪个课程(2022-2023-1-计算机基础与程序设计)这个作业要求在哪里(2023-2024-1计算机基础与程序设计第2周作业)这个作业的目标自学《计算机科学概论》《C语言程序设计》第1章并完成云......
  • 2023-2024-1 20231323 《计算机基础与程序设计》第二周学习总结
    2023-2024-120231323《计算机基础与程序设计》第2周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第二周作业这个作业的目标数字化、信息安全与自学教材《计算机科学概论》《C语言程......
  • 2023-2024-1 20231305 《计算机基础与程序设计》第2周学习总结
    2023-2024-120231305《计算机基础与程序设计》第2周学习总结作业信息这个作业属于哪个课程<班级的链接>(如2022-2023-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2022-2023-1计算机基础与程序设计第一周作业)这个作业的目标<阅读《计算机科学......
  • 2023-2024-1 20231420 《计算机基础与程序设计》第二周学习总结
    2023-2024-120231420《计算机基础与程序设计》第二周学习总结作业信息这个作业属于哪个课程2023-2024-1《计算机基础与程序设计》这个作业要求在哪里2023-2024-1计算机基础与程序设计第二周作业这个作业的目标1.学习《计算机科学概论》第1章并完成云班课测试;2.......
  • 【Cucumber】关于BDD自然语言自动化测试的语法总结
    1、关键字-Feature每一个.feature文件必须以关键字Feature开始,Feature关键字之后可以添加该feature的描述,其作用类似于注释,仅仅为了便于理解沟通交流,描述内容中不可以包含Gherkin关键字,描述部分将不会被执行。2、关键字-Scenario一个feature可以包含多个Scenario,每一个Scen......