Studying-代码随想录训练营day48| 739. 每日温度、496.下一个更大元素 I、503.下一个更大元素II

第48天,单调栈part01,栈的特殊应用场所!编程语言:C++

目录

739. 每日温度

496.下一个更大元素 I

503.下一个更大元素II

总结:


739. 每日温度

文档讲解:代码随想录每日温度

视频讲解:手撕每日温度

题目: 739. 每日温度 - 力扣(LeetCode)

学习:本题是单调栈的第一道题。本题直观的解决办法是采用双层循环,一层遍历当前元素,一层遍历后续元素并找到比当前元素大的值,以此来进行求解,时间复杂度为O(n^2)。

但本题可以采用单调栈的方式,降低时间复杂度,单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

单调栈的主要使用场景就是寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置。最终实现的复杂度为O(n)。注意单调栈中存放的应该是遍历过的元素。

在每一题使用单调栈前我们需要注意两点:1. 单调栈里存放的元素是什么?2. 单调栈里的元素是递增呢?还是递减呢?(这个的递增递减是从栈顶往栈底看的)

在本题中,我们可以在单调栈中存放元素下标,以方便我们记录下一个更大元素的位置。同时我们要找的是比当前元素大的元素,因此我们单调栈应该采取递增的方式,比当前元素小,就加入栈中。

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

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

代码:我们可以通过代码,直观感受单调栈的使用:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int> result(temperatures.size(), 0); //返回的答案数组stack<int> st; //单调栈:适合查找左边或者右边,第一个比当前元素大或者小的元素st.push(0); //放入第一个元素,注意放入的应该是下标for(int i = 1; i < temperatures.size(); i++) {if(temperatures[i] <= temperatures[st.top()]) { //如果当前元素比栈顶元素小,则加入栈中st.push(i);}else { //如果当前元素比栈顶元素大,则要开始弹出while(!st.empty() && temperatures[i] > temperatures[st.top()]) { //注意这个地方必须要用循环result[st.top()] = i - st.top();st.pop();}st.push(i);}}return result;}
};

代码:我们也可以将上述代码简化,因为无论如何我们都会有st.push(i)这一步存在。

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int> result(temperatures.size(), 0); //返回的答案数组stack<int> st; //单调栈:适合查找左边或者右边,第一个比当前元素大或者小的元素st.push(0); //放入第一个元素,注意放入的应该是下标for(int i = 1; i < temperatures.size(); i++) {while(!st.empty() && temperatures[i] > temperatures[st.top()]) {result[st.top()] = i - st.top();st.pop();}st.push(i);}return result;}
};

496.下一个更大元素 I

文档讲解:代码随想录下一个更大元素I

视频讲解:手撕下一个更大元素I

题目:496. 下一个更大元素 I - 力扣(LeetCode)

学习:本题也是找下一个更大元素,解题的核心思路是一样的。只不过本题还需要解决一个问题,就是nums1到nums2的映射问题,解决这个问题我们可以采用哈希表的方法,把nums1的元素加入到哈希表中,之后在nums2内通过查找哈希表的方式,进行相关元素的赋值。

这里要注意,我们遍历的一定是nums2,因为我们要找的是nums2中下一个更大元素。

同时本题单调栈中,我们可以存取下标(然后通过下标来找到对应元素),也可以存取元素,因为本题我们需要找的是最大元素,而不是下标位置。

代码:存取下标的方式

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int> st;vector<int> result(nums1.size(), -1);if (nums1.size() == 0) return result;unordered_map<int, int> umap; // key:下标元素,value:下标for (int i = 0; i < nums1.size(); i++) {umap[nums1[i]] = i;}st.push(0);for (int i = 1; i < nums2.size(); i++) {while (!st.empty() && nums2[i] > nums2[st.top()]) {if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标result[index] = nums2[i];}st.pop();}st.push(i);}return result;}
};

代码:存取元素的方式

class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int> result(nums1.size(), -1); //记录答案unordered_map<int, int> umap; //使用哈希表构建nums1和nums2的关系for(int i = 0; i < nums1.size(); i++) {umap[nums1[i]] = i;}stack<int> st; //单调栈,栈顶到栈底从小到大st.push(nums2[0]);for(int i = 0; i < nums2.size(); i++) {while(!st.empty() && nums2[i] > st.top()) {if(umap.count(st.top()) != 0) {result[umap[st.top()]] = nums2[i];}st.pop();}st.push(nums2[i]);}return result;}
};

503.下一个更大元素II

文档讲解:代码随想录下一个元素更大II

视频讲解:手撕下一个元素更大II

题目: 503. 下一个更大元素 II - 力扣(LeetCode)

学习:本题相较于上一题其实更为简单,本题我们主要需要解决的是循环数组的问题。关于这个问题有两个求解办法。

1.通过扩展数组的方式,实现循环数组。也就是将两个nums数组拼接到一起,然后使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。

代码:

//时间复杂度O(n)
//空间复杂度O(2n)
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {// 拼接一个新的numsvector<int> nums1(nums.begin(), nums.end());nums.insert(nums.end(), nums1.begin(), nums1.end());// 用新的nums大小来初始化resultvector<int> result(nums.size(), -1);if (nums.size() == 0) return result;// 开始单调栈stack<int> st;st.push(0);for (int i = 1; i < nums.size(); i++) { if (nums[i] < nums[st.top()]) st.push(i); else if (nums[i] == nums[st.top()]) st.push(i);else { while (!st.empty() && nums[i] > nums[st.top()]) {result[st.top()] = nums[i];st.pop();}st.push(i);}}// 最后再把结果集即result数组resize到原数组大小result.resize(nums.size() / 2);return result;}
};

2.也可以采用取余的方式进行循环数组求解,这个方式也是目前比较好的方式,后面碰到循环数组,都可以采取取余的方式进行求解。本质上就是通过取余来遍历数组两次。

代码:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {vector<int> result(nums.size(), -1); //记录答案返回数组if(nums.size() == 0) return result;stack<int> st; //单调栈st.push(0); for(int i = 0; i < nums.size() * 2; i++) { //使用取余的方法,模拟环形数组while(!st.empty() && nums[i % nums.size()] > nums[st.top()]) { //单调栈处理逻辑result[st.top()] = nums[i % nums.size()];st.pop();}st.push(i % nums.size());}return result;}
};

总结:

牢记单调栈应用场所,解决寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置的问题。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

AI识别智能称重-收银系统源码

系统概况 专门为零售行业的连锁店量身打造的收银系统&#xff0c;适用于常规超市、生鲜超市、水果店、便利店、零食专卖店、服装店、母婴用品、农贸市场等类型的门店使用。同时线上线下数据打通&#xff0c;线下收银的数据与小程序私域商城中的数据完全同步&#xff0c;如商品…

什么是数据血缘?怎么做好数据血缘分析?

目录 一、什么是数据血缘&#xff1f; 二、数据血缘关系的四大特征 三、数据血缘分析怎么做&#xff1f; 1.定义元数据模型 2.收集元数据 3.建立血缘关系模型 4.追踪数据流动 5.可视化分析 6.集成到数据治理中 7.持续更新和维护 8.应用分析结果 四、数据血缘技术趋势 1.通用的血…

测试环境领域到测试环境产品

作者&#xff1a;攻心 去年之前&#xff0c;阿里巴巴的淘天集团测试环境是以领域方式运作&#xff1a;不局限测试环境治理本身&#xff0c;从测试模式方法论及用好测试环境思路引领集团测试环境治理。领域运作最难的是“统一思想”。业务进一步细分调整后&#xff0c;测试环境治…

修改所属用户/用户组——chown

目录 &#xff08;1&#xff09;修改所属用户 &#xff08;2&#xff09;修改所属用户组 &#xff08;3&#xff09;修改所属用户和用户组 &#xff08;4&#xff09; 选项 -R 使用 chown 可以修改文件/文件夹的所属用户&#xff0c;所属用户组&#xff1b; 当然与 chmod …

数字人直播系统搭建能力评测!3招教你快速摸清源码厂商的真实实力?

随着数字人直播的应用场景不断拓展和应用频率的持续升高&#xff0c;其所蕴含着的市场前景和收益潜力逐渐显现&#xff0c;连带着数字人直播系统搭建的热度也迎来了新的高潮。在此背景下&#xff0c;作为非科班和研发资源有限的创业者们主要的入局途径&#xff0c;各大数字人源…

C++原创系列创斯人工智能Trons10.0.135.7911最新概念版本预告及思路总结

这次更新删掉了以前的所有代码&#xff0c;重新编写&#xff0c;只因我有了新的思路&#xff0c;以前的思路太过于原始&#xff0c;我的思路中的聊天功能如下 这只是聊天函数的原理&#xff0c;聊天函数对一句话的回答有5个到10个&#xff0c;在主函数中多次运行这个函数&#…

ruoyi vue3版本web端隐藏侧边栏及其顶部导航栏

做项目时有个需求是在web端里面嵌入一个页面全屏的大屏&#xff0c;但若依web自带的侧边栏导航和顶部导航一时还不知道怎么隐藏起来&#xff0c;于是在网上到处查找资料&#xff0c;终于&#xff0c;还是在若依的gitee文档中发现了线索 怎么隐藏侧边栏和顶部导航栏实现完全的全…

<数据集>工程机械识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;6338张 标注数量(xml文件个数)&#xff1a;6338 标注数量(txt文件个数)&#xff1a;6338 标注类别数&#xff1a;7 标注类别名称&#xff1a;[Excavator, Loader, Dumb_truck, Mobile_crane, Roller, Bull_dozer, …

微信小程序之使用智能对话服务,客服回复的跳转小程序指定页面链接无效

在微信小程序中使用了微信智能对话服务&#xff0c;客服回复的是小程序指定页面的链接&#xff0c;无法正确跳转&#xff0c;而是返回到进入客服时的页面去了 解决方案&#xff1a; 需在小程序的客服组件 button 上添加 bindcontact 监听事件即可 <movable-area class"…

【ROS 最简单教程 007/300】ROS 架构 - 目录解析 增删改查 计算图

⭐ 工作空间目录解析如下 &#xff1a; WorkSpace --- 自定义的工作空间|--- build:编译空间&#xff0c;用于存放 CMake 和 catkin的 缓存信息、配置信息和其他中间文件|--- devel:开发空间&#xff0c;用于存放编译后生成的目标文件&#xff0c;包括头文件、动态&静态链接…

MySQL基础练习题14-产品销售分析1

题目&#xff1a;获取 Sales 表中所有 sale_id 对应的 product_name 以及该产品的所有 year 和 price 。 准备数据 分析数据 题目&#xff1a;获取 Sales 表中所有 sale_id 对应的 product_name 以及该产品的所有 year 和 price 。 准备数据 ## 创建库 create database db;…

DNS查询服务器的基本流程以及https的加密过程

DNS查询服务器的基本流程&#xff0c;能画出图更好&#xff0c;并说明为什么DNS查询为什么不直接从单一服务器查询ip&#xff0c;而是要经过多次查询&#xff0c;多次查询不会增加开销么&#xff08;即DNS多级查询的优点&#xff09;&#xff1f; 用户发起请求&#xff1a;用户…

Linux 修改磁盘挂载的目录路径

确认新路径地址&#xff0c;能找到&#xff0c;或者mkdir新创建新路径&#xff0c;考虑权限 #查看当前挂载情况 df -h 卸载已经挂载的目录 umount /media/vdtest #挂载新目录 mount /dev/vdb /mnt #查询/dev/vdb的UUID blkid /dev/vdb #修改 fstab文件实现开机自动挂载&…

Spring源码解析(25)之AOP的BeanDefinitiion准备

一、AOP代码准备 aop.xml文件准备&#xff0c;代码如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance…

汇川技术|CANlink、CANopen、Profibus-DP网络编辑器的使用

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 本节学习CANlink、CANopen、Profibus-DP网络编辑器的使用。 以下为学习笔记。 01 CANlink编辑器 在AC810的【网络组态】中未看到CANlink主站的功能&#xff0c;所以先简单了解&#xff0c;等具体使用时再具体查看。 …

2025上海国际显示技术及应用创展览会

DIC EXPO2025中国&#xff08;上海&#xff09;国际显示技术及应用创展览会 时间&#xff1a;2025年8月7-9日 地点&#xff1a;上海新国际博览中心 主办单位&#xff1a; 中国光学光电子行业协会液晶分会 联合主办&#xff1a; 中国电子材料行业协会 中国电子商会 韩国…

【iOS】——持久化

在iOS开发中&#xff0c;数据持久化是非常重要的&#xff0c;因为它允许应用程序在不同会话之间保存用户数据、设置、偏好等信息。 为什么数据持久化 数据保存&#xff1a; 目的&#xff1a;将应用程序中的数据保存到非易失性存储中&#xff0c;以便在应用程序关闭或重启后仍…

对零基础想转行网络安全同学的一点建议

最近有同学在后台留言&#xff0c;0基础怎么学网络安全&#xff1f;0基础可以转行做网络安全吗&#xff1f;以前也碰到过类似的问题&#xff0c;想了想&#xff0c;今天简单写一下。 我的回答是先了解&#xff0c;再入行。 具体怎么做呢&#xff1f; 首先&#xff0c;你要确…

WIFI7在游戏领域引发的变革

随着无线技术的快速进步&#xff0c;游戏体验正变得愈加丰富、复杂和逼真。现在最新的WIFI 7技术将带来新的飞跃&#xff0c;不仅有望重新定义网络游戏的体验&#xff0c;还有可能彻底革新整个游戏产业。可以想象一下&#xff0c;在未来&#xff0c;游戏世界不再有延迟和连接中…

VirtualFlow案例 | 油箱燃油晃动模拟,高效分析管路及油箱内油面变化

在探索流体行为模拟的领域&#xff0c;CFD技术为油箱燃油晃动模拟带来了革命性的转变。通过高精度的数值模拟&#xff0c;它不仅揭示了燃油在不同工况下的复杂动态&#xff0c;还为油箱设计的优化提供了关键洞察。这一技术在航空航天、汽车制造、船舶与海洋工程等多个行业中展现…