代码随想录算法训练营第五十八天丨 单调栈01

739. 每日温度

思路

首先想到的当然是暴力解法,两层for循环,把至少需要等待的天数就搜出来了。时间复杂度是O(n^2)

那么接下来在来看看使用单调栈的解法。

 什么时候用单调栈呢?

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

例如本题其实就是找找到一个元素右边第一个比自己大的元素,此时就应该想到用单调栈了。

那么单调栈的原理是什么呢?为什么时间复杂度是O(n)就可以找到每一个元素的右边第一个比它大的元素位置呢?

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。

在使用单调栈的时候首先要明确如下几点:

  • 单调栈里存放的元素是什么?

单调栈里只需要存放元素的下标 i 就可以了,如果需要使用对应的元素,直接T[i]就可以获取。

  • 单调栈里元素是递增呢? 还是递减呢?

注意以下讲解中,顺序的描述为 从栈头到栈底的顺序,因为单纯的说从左到右或者从前到后,不说栈头朝哪个方向的话,大家一定比较懵。

这里我们要使用递增循序(再强调一下是指从栈头到栈底的顺序),因为只有递增的时候,栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i。

即:如果求一个元素右边第一个更大元素,单调栈就是递增的,如果求一个元素右边第一个更小元素,单调栈就是递减的。

文字描述理解起来有点费劲,接下来我画了一系列的图,来讲解单调栈的工作过程,大家再去思考,本题为什么是递增栈。

使用单调栈主要有三个判断条件。

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

把这三种情况分析清楚了,也就理解透彻了

接下来我们用temperatures = [73, 74, 75, 71, 71, 72, 76, 73]为例来逐步分析,输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。


首先先将第一个遍历元素加入单调栈

739.每日温度1


加入T[1] = 74,因为T[1] > T[0](当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况)。

我们要保持一个递增单调栈(从栈头到栈底),所以将T[0]弹出,T[1]加入,此时result数组可以记录了,result[0] = 1,即T[0]右面第一个比T[0]大的元素是T[1]。

739.每日温度2


加入T[2],同理,T[1]弹出

739.每日温度3


加入T[3],T[3] < T[2] (当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况),加T[3]加入单调栈。

739.每日温度4


加入T[4],T[4] == T[3] (当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况),此时依然要加入栈,不用计算距离,因为我们要求的是右面第一个大于本元素的位置,而不是大于等于!

739.每日温度5


加入T[5],T[5] > T[4] (当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况),将T[4]弹出,同时计算距离,更新result 

739.每日温度6


T[4]弹出之后, T[5] > T[3] (当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况),将T[3]继续弹出,同时计算距离,更新result 

739.每日温度7


直到发现T[5]小于T[st.top()],终止弹出,将T[5]加入单调栈

739.每日温度8


加入T[6],同理,需要将栈里的T[5],T[2]弹出

739.每日温度9


同理,继续弹出

739.每日温度10


此时栈里只剩下了T[6]

739.每日温度11


加入T[7], T[7] < T[6] 直接入栈,这就是最后的情况,result数组也更新完了。

739.每日温度12

此时可能就疑惑了,那result[6] , result[7]怎么没更新啊,元素也一直在栈里。

其实定义result数组的时候,就应该直接初始化为0,如果result没有更新,说明这个元素右面没有更大的了,也就是为0。

以上在图解的时候,已经把,这三种情况都做了详细的分析。

  • 情况一:当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 情况二:当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 情况三:当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

通过以上过程,大家可以自己再模拟一遍,就会发现:只有单调栈递增(从栈口到栈底顺序),就是求右边第一个比自己大的,单调栈递减的话,就是求右边第一个比自己小的。

代码如下:

class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] answer = new int[temperatures.length];//小的话一直压栈记录,大的话就下表相减求距离/**如果当前遍历的元素 大于栈顶元素,表示 栈顶元素的 右边的最大的元素就是 当前遍历的元素,所以弹出 栈顶元素,并记录如果栈不空的话,还要考虑新的栈顶与当前元素的大小关系否则的话,可以直接入栈。注意,单调栈里 加入的元素是 下标。*/Stack<Integer> st = new Stack<>();st.push(0);for (int i = 1; i < temperatures.length; i++) {if (temperatures[i] > temperatures[st.peek()]){//如果当前元素大于栈顶元素//遍历栈,如果碰到当前元素小于等于栈顶元素时,将当前元素的下标放入栈中//如果当前元素大于栈顶元素,栈顶元素为下标的值为 i- st.popwhile (!st.isEmpty() && temperatures[i] > temperatures[st.peek()]){if (temperatures[i] > temperatures[st.peek()]){int stIndex = st.pop();answer[stIndex] = i - stIndex;}}st.push(i);}else {//当前元素小于等于栈顶元素st.push(i);}}return answer;}
}

496.下一个更大元素 I

思路

这题秒了基本没看卡哥的题解,但思路基本也是与卡哥的一致。但需要注意的细节点是,每次 i 遍历完之后需要对栈stack 进行清空处理,防止本次遗留元素影响到下一次层的循环中。

并且我将结果数组 res[] 均初始化为了-1,具体思路见代码:

class Solution {public int[] nextGreaterElement(int[] nums1, int[] nums2) {//nums1 是 nums2 的子集int[] res = new int[nums1.length];Arrays.fill(res,-1);Stack<Integer> st = new Stack<>();//找出num1[i] == num2[j]的j 值for (int i = 0; i < nums1.length; i++) {for (int j = 0; j < nums2.length; j++) {if (nums1[i] == nums2[j]){//确定 nums2[j] 的 下一个更大元素st.push(j);}if (!st.isEmpty() && nums2[j] > nums2[st.peek()]){res[i] = nums2[j];st.pop();}}st.clear();}return res;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/150772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 的执行原理(二)

5.3. MySQL 的查询成本 5.3. MySQL 的查询成本 MySQL 执行一个查询可以有不同的执行方案&#xff0c;它会选择其中成本最低&#xff0c;或者 说代价最低的那种方案去真正的执行查询。不过我们之前对成本的描述是非常模 糊的&#xff0c;其实在 MySQL 中一条查询语句的执行成本…

Cmake学习

cmake大致 cmake_minimum_required(VERSION 3.0)project(test) #通过set自定义变量&#xff0c;通过${}取出 #set(SRC add.cpp main.cpp muti.cpp sub.cpp) #cmake搜索文件 宏定义PROJECT_SOURCE_DIR aux_source_directory(${PROJECT_SOURCE_DIR} SRC) #file(GLOB/GLOB_RECURSE…

静态文件鉴权

​ 静态文件鉴权的解决方案 背景介绍 XX业务系统作为BXX业务系统的孪生姐妹系统&#xff0c;是对BXX受理业务的强力补充系统&#xff0c;他允许操作员拿着IPAD&#xff0c;和客户约定地点上门受理业务。 因一些业务的受理&#xff0c;按照最新的业务规章制度&#xff0c;需…

常用 API 异常

常用 API & 异常 对之前那篇 API 文章的补充学习 1.API 1.1 API概述【理解】 什么是API ​ API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&am…

OpenCV快速入门:窗口交互

文章目录 前言一、鼠标操作1.1 鼠标操作简介1.2 鼠标事件类型&#xff08;event类型&#xff09;1.3 鼠标事件标志&#xff08;flags&#xff09;1.4 代码示例1.4.1 获取鼠标坐标位置1.4.2 监听鼠标滚轮事件1.4.3 在图像中显示鼠标坐标 二、键盘操作2.1 代码示例2.2 waitKey的等…

ssm家长乐山美食网站系统

1.需求分析\n将进行家乡乐山美食网站的需求分析。需求分析是系统开发过程中的一项重要工作&#xff0c;它是对用户需求进行深入研究和分析&#xff0c;明确系统的功能、性能、界面等方面的需求&#xff0c;为后续的设计和开发提供依据。\n首先&#xff0c;需要明确该网站的主要…

制作Go程序的Docker容器(以及容器和主机的网络问题)

今天突然遇到需要将 Go 程序制作成 Docker 的需求&#xff0c;所以进行了一些研究。方法很简单&#xff0c;但是官方文档和教程有些需要注意的地方&#xff0c;所以写本文进行记录。 源程序 首先介绍一下示例程序&#xff0c;示例程序是一个 HTTP 服务器&#xff0c;会显示si…

【GUI】-- 11 贪吃蛇小游戏之绘制静态的小蛇

GUI编程 04 贪吃蛇小游戏 4.2 第二步&#xff1a;绘制静态的小蛇 现在绘制静态的小蛇(即小蛇初始位置)&#xff0c;并且完善游戏默认初始状态。这一步还在GamePanel类中实现。 首先&#xff0c;定义了小蛇的数据结构&#xff0c; //定义蛇的数据结构int length; //小蛇总长…

yolo系列模型训练数据集全流程制作方法(附数据增强代码)

yolo系列的模型在目标检测领域里面受众非常广&#xff0c;也十分流行&#xff0c;但是在使用yolo进行目标检测训练的时候&#xff0c;往往要将VOC格式的数据集转化为yolo专属的数据集&#xff0c;而yolo的训练数据集制作方法呢&#xff0c;最常见的也是有两种&#xff0c;下面我…

开源与闭源:大模型发展的双重走向

目录 前言开源和闭源的优劣势比较开源的优势闭源的优势 开源和闭源对大模型技术发展的影响对技术发展的影响对数据共享的影响对业务拓展的影响 开源与闭源的商业模式比较开源的商业模式闭源的商业模式 处在大模型洪流中&#xff0c;向何处去&#xff1f;结语 前言 随着人工智能…

中国智能音箱市场销量下降,百度稳居第一 /中国即评出10个大模型创新案例 |魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件&#x1f525;&#xff0c;更新AIGC的最新动态&#xff0c;生成相应的魔法简报&#xff0c;节省阅读时间&#x1f47b; 中国智能音箱市场销量下降&#xff0c;百度稳居第一 中国即将评选出10个最具代表性的大模型创新案例…

【Typroa使用】Typroa+PicGo-Core(command line)+gitee免费图片上传配置

TyproaPicGo-Core(command line)gitee免费图片上传配置 本文是在win10系统下配置typroapicGo-Core(command line)gitee图片上传的教程。需要的环境和工具有&#xff1a; gitee账号&#xff0c;新建仓库及token令牌&#xff1b;已经安装了的typroa&#xff0c;需要0.9.98版本以上…

2023最全的性能测试种类介绍,这6个种类特别重要!

系统的性能是一个很大的概念&#xff0c;覆盖面非常广泛&#xff0c;包括执行效率、资源占用、系统稳定性、安全性、兼容性、可靠性、可扩展性等&#xff0c;性能测试就是描述测试对象与性能相关的特征并对其进行评价而实施的一类测试。 性能测试是一个统称&#xff0c;它其实包…

大数据Doris(二十五):Stream Load数据导入演示和其他导入案例

文章目录 数据导入演示和其他导入案例 一、数据导入演示

【Web】Ctfshow SSRF刷题记录1

核心代码解读 <?php $url$_POST[url]; $chcurl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $resultcurl_exec($ch); curl_close($ch); ?> curl_init()&#xff1a;初始curl会话 curl_setopt()&#xff1a;会…

水质测定仪的优势特点有哪些?

水质测定仪&#xff1a;水环境保护的得力助手 随着人们环保意识的不断提高&#xff0c;水质问题逐渐引起了大家的关注。为了保护水环境&#xff0c;必须加强对污水排放的监测&#xff0c;而水质测定仪在这个过程中扮演着重要的角色。 水质测定仪是一种专业的仪表&#xff0c;主…

旋极携手西班牙SoC-e公司,为中国客户提供高效可靠TSN通讯解决方案

2023年2月&#xff0c;旋极信息与西班牙SoC-e公司正式签订战略合作协议&#xff0c;成为其在中国区重要合作伙伴。 SoC-e是一家世界领先的基于FPGA技术的以太网通讯解决方案供应商&#xff0c;是一系列IP核开发领域的先锋&#xff0c;为关键任务实施网络化、同步性和安全性提供…

如何使用贝锐花生壳内网穿透远程访问JupyterNotebook?

在数据科学领域&#xff0c;Jupyter Notebook 已成为处理数据的必备工具。 其用途包括数据清理和探索、可视化、机器学习和大数据分析。Jupyter Notebook的安装非常简单&#xff0c;如果你是小白&#xff0c;那么建议你通过安装Anaconda来解决Jupyter Notebook的安装问题&#…

【23真题】超难985!做完感觉没学过!

本套试卷难度分析&#xff1a;22年西北工业大学827考研真题&#xff0c;我也发布过&#xff0c;若有需要&#xff0c;戳这里自取&#xff01;本套试题内容有难度&#xff0c;题目考察全为大题&#xff0c;题目不多&#xff01;但是题目都很新颖&#xff0c;状态方程的题目考察较…