Leetcode901-股票价格跨度

news2024/10/6 12:21:46

一、前言

本题基于leetcode901股票价格趋势这道题,说一下通过java解决的一些方法。并且解释一下笔者写这道题之前的想法和一些自己遇到的错误。需要注意的是,该题最多调用 next 方法 10^4 次,一般出现该提示说明需要注意时间复杂度。

二、解决思路

①栈排序(存在超出时间限制问题)

其实笔者做这道题之前并不知道单调栈这一东西,第一时间想到的是很像之前做过的和栈相关的一道题–栈排序,毕竟都是类似按照某一顺序对栈元素进行排序。需要借用辅助栈,而考虑到它需要计算的是连续天数,不是一个简单的排序。
拿这道题给的示例输入来说:
在这里插入图片描述
思路就是如果是空栈,那么我们直接放就好。
而当不是空栈时,此时通过price和栈顶元素的差值区分情况:
①小于0:
说明price要小,那么我们直接入栈,然后由于此时栈肯定没有比price更小的元素,所以只有它自己,return 1即可
②大于等于0:
说明此时price要大于栈顶元素,由于它要的是最大连续日数(从今天开始往回数,包括今天),那么我必须得保持入栈的一个顺序,否则就不是连续的,而是一个比当前price要小的所有天数这样一个结果
那么怎样处理呢,我们可以先将该price入辅助栈,然后再从栈顶遍历,将小于等于当前price的栈元素弹出push到辅助栈中。此时记录辅助栈的size就是我们要返回的最大连续天数,最后再将辅助栈一次push到我们的主栈中即可
我这边画一个图:
在这里插入图片描述
如上图,第一次入栈70这个元素时,比栈顶元素60要大,将price=70入辅助栈,然后遍历主栈栈顶,将小于等于70的元素弹出栈然后push进辅助栈,此时记录辅助栈size为2,然后将辅助栈元素全部弹出并且推入主栈,最后返回size即可。且这样不会修改我主栈元素的原本顺序,就是按照next元素的顺序进行排序的,就也顺便解决了连续这个问题。
同理,后面入75如下图所示:
在这里插入图片描述
代码如下:

class StockSpanner {

private Stack<Integer> stockStack;
	private Stack<Integer> diffStack;

	public StockSpanner() {
		stockStack = new Stack<>();
		diffStack = new Stack<>();
	}

	public int next(int price) {
		if (stockStack.isEmpty()) {
			stockStack.push(price);
			return 1;
		} else {
			int diff = price - stockStack.peek();
			if (diff < 0) {
				stockStack.push(price);
				return 1;
			} else {
			diffStack.push(price);
			while (!stockStack.isEmpty() && stockStack.peek() <= price) {
					diffStack.push(stockStack.pop());
				}
				
				int res = diffStack.size();
				while (!diffStack.isEmpty()) {
					stockStack.push(diffStack.pop());
				}
				return res;
			}
		}
	}
}

好像这样思路确实没什么问题,运行发现超出时间限制o(╥﹏╥)o:
在这里插入图片描述

虽说时间复杂度是O(n),可是这样的操作确实还是非常繁琐的,且还需要借助辅助栈且最后主栈的元素量是Next()的调用次数,无效或者其实用不上的元素根本没有pop出栈,导致浪费了很多空间。
所以也就有了后面一种方法–单调栈,该方法不再需要辅助栈,且不会浪费额外空间。

②单调栈

我们将每一个股票价格想象成java的一个对象,它拥有它的id,拥有它的价格,我们可以使用一个int[]去承装他们,int[0]装id,int[1]装价格。
然后我们可以想象下,我们需要比今日股票要小于等于的天数,是否就是将这些对象给按照一个单调递减的顺序排序,如果放入的元素比上一个元素要小,此时结果就是当前放入元素的下标id和上一个元素下标的差值。如果要大,此时不符合单调递减,那么我需要将比它小的元素全部抹去,让我们承装对象的结构始终符合单调递减,此时结果是当前当如元素的下标id和抹去后的它的上一个元素下标id的差值。
为了方便我们后续程序少一些空栈之类的判断,我们初始化的时候可以先push进一个id为0,价格是Integer.MAX的元素,这样到时候我们出栈也不用担心会导致空栈
而对于next方法,首先是下标,这个很好理解,我们每次调用next方法时,id++即可,很像我们数据库的ID自增策略。由于我们需要的是小于或等于今天价格的最大连续日数,所以是一个单调递减栈,如果要插入的price大于栈顶元素,此时将单调栈的元素依次弹出,并且此时将当前price对应的下标减去出栈后的栈顶元素的下标,这个下标差就是我们需要返回的结果。然后再将当前元素入栈即可然后返回下标差即可。
仍然拿示例1举例:
当我插入100-80-60,由于每次插入都比栈顶元素要小,而当插入70时,此时比栈顶元素60要大,从栈顶开始遍历,一直到栈顶元素大于price为止,此时出栈完后栈顶是id=2,price=80这个元素,然后记录res=4-2=2,然后将price=70,id=4这个元素入栈。
在这里插入图片描述
放入60,75同理:
在这里插入图片描述
代码如下:

class StockSpanner {

private Deque<int[]> stockStack;
	private int id;

	public StockSpanner() {
		stockStack = new ArrayDeque<>();
		stockStack.push(new int[]{0,Integer.MAX_VALUE});
		id = 0;
	}

	public int next(int price) {
		id ++;
		while (price >= stockStack.peek()[1]){
			stockStack.pop();
		}
		int ret = id - stockStack.peek()[0];
		stockStack.push(new int[]{id, price});
		return ret;
  }
}

在这里插入图片描述

三、栈排序和单调栈的区别

那么其实栈排序和单调栈是有明显区别的,这里做一个总结:

单调栈单调栈是一种特殊的栈结构,其插入时保证栈内元素的单调性。通常用于解决数组中下一个更大或下一个更小元素的问题。例如我们可以见我们力扣496下一个更大元素 I这道题,单调栈需要维护一个单调递增或单调递减的栈顶元素序列,每当新元素插入时,都需要判断该元素与栈顶元素的大小关系,不断弹出栈顶元素直到满足单调性。

栈排序:栈排序是对栈内元素进行递增或递减排序的一种思路。通常使用额外的栈来辅助排序。将原始栈的元素依次弹出,插入到辅助栈中的正确位置,最后将辅助栈中的元素重新压回原始栈中,从而实现了栈排序。需要注意的是,仅使用原始栈是无法实现栈排序的,因为栈的弹出顺序一旦改变就无法恢复

总体来说,单调栈和栈排序都是基于栈实现的常用算法思路,但其应用场景和实现方法不同。单调栈通常用于解决比较问题,需要维护栈内元素的单调性;而栈排序则是对栈内元素的排序,需要额外借助辅助栈实现

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

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

相关文章

苹果手机的祛魅时刻,国产厂商的颠覆征程

“iPhone翻车了&#xff1f;”有网友如此质疑。 发布未满一个月&#xff0c;iPhone 15系列多次因负面问题登上热搜。 首先曝出钛金属边框容易沾染指纹的情况&#xff0c;尚未涉及功能性方面&#xff0c;但后续接连曝出发热严重、电池循环次数低、外放破音、Wi-Fi链接缓慢的问…

Android系统启动之init进程启动+Zygote进程启动分析

一、基础概念理解 init进程 Android系统所有进程的祖先&#xff0c;是Android系统内核初始化完毕后&#xff0c;进入用户空间启动的第一个进程。 Android虚拟机 Dalvik虚拟机是谷歌自己设计的用于Android平台的虚拟机。Android4.4同时提供了Dalvik和ART虚拟机。Android5.0以后…

重庆建筑模板厂家:选择桉木模板,智慧之选

随着城市化进程的不断加速&#xff0c;建筑业也呈现出蓬勃发展的势头。而作为建筑过程中不可或缺的材料之一&#xff0c;建筑模板的选择将直接影响到工程质量和工期。在重庆这样一个气候多变、地形复杂的地区&#xff0c;如何选择适合当地情况的建筑模板显得尤为重要。 一、常规…

《第一行代码Andorid》阅读笔记-第六章

第六章 内容提供器 在上一章中我们学了Android数据持久化的技术&#xff0c;包括文件存储、SharedPreferences存储以及数据库存储。使用这些持久化技术所保存的数据都只能在当前应用程序中访问。 虽然文件和SharedPreferences存储中提供了MODE_WORLD_READABLE和MODE_WORLD_WRI…

电脑系统一键重装Win10操作方法教程

如果我们的电脑系统遇到了运行变慢、感染病毒等问题&#xff0c;这时候我们就可以进行系统的重装&#xff0c;这样来解决遇到的系统问题。特别多的用户都想知道一键重装Win10系统的详细步骤&#xff0c;下面小编就给大家带来最详细的操作方法介绍哦&#xff0c;帮助大家轻松完成…

【Vue基础-数字大屏】地图

一、阿里云数据可视化平台 地图数据https://datav.aliyun.com/portal/school/atlas/area_selector 二、操作步骤 1、打开阿里云数据可视化平台&#xff0c;复制中国地图数据链接 2、在浏览器中打开中国地图数据链接&#xff0c;复制json数据 3、在assets静态目录下创建mapDa…

大数据获客是什么?有什么用?

随着企业部分业务线上化、目标用户下沉&#xff0c;风控体系也在迭代&#xff0c;依靠大数据、人工智能进行风控成为行业共识。另一方面&#xff0c;随着线上线下获客成本日益增长&#xff0c;各机构逐渐转向用户精细化经营&#xff0c;精准营销受到各企业机构重视。大数据精准…

基于SSM的大学生创新创业平台竞赛管理子系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

维修派工单,为什么要使用维修派工单

维修派工单是一种至关重要的管理工具&#xff0c;主要用于分配维修人员对设备进行维护和维修。根据派工单&#xff0c;可以快速清晰地分配维修任务&#xff0c;掌握设备维护的进度和效果&#xff0c;提升设备维护的效率和效果。  良好的维修工单应具有清晰的格式&#xff0c;…

具有隔离功能,1Mbps,高速 CAN 总线收发器:SIT1050ISO

SIT1050ISO 是一款电容隔离的 CAN 转发器&#xff0c; ISO11898 标准的技术规范&#xff0c;含有多个由二氧化 硅&#xff08; SiO2 &#xff09;绝缘隔栅分开的逻辑输入和输出缓冲器&#xff0c;具有在总线与 CAN 协议控制器之间进行差分 信号传输的能力。 产品特点&a…

智慧电力运维系统助力实现配电室无人值守

随着科技的快速发展&#xff0c;电力行业也在变革&#xff0c;不断追求高效、安全和可靠的供电服务。传统的电力运维模式存在成本高、人工操作和监控存在一定的局限性和安全隐患&#xff0c;已无法满足现代电力企业的需求&#xff0c;电力企业需要更加智能化、高效化、安全化&a…

SSL证书是什么?1分钟get

在当今互联网世界中&#xff0c;保护数据的完整性和隐私性至关重要&#xff0c;由此&#xff0c;在网络数据安全保护领域&#xff0c;作为保护网络传输数据安全的SSL证书越来越频繁出现。那么你知道SSL证书是什么&#xff1f;SSL证书有哪些类型&#xff1f;SSL证书有什么用吗&a…

SAP从入门到放弃系列之QM目录类别、代码组、选择集维护

目录 一、概念相关内容1.1 目录类别1.2 代码组和代码1.3 选择集和选择集代码 二、系统操作相关内容 一、概念相关内容 1.1 目录类别 目录类别是对定性数据的一种归纳&#xff0c;描述了业务的主题。根据PA的教材中表述&#xff0c;目录类型 0 - 9 和 A - O 由 SAP 定义&#…

在全志XR806开发板使用编码器进行调光

XR806识别编码器和PWM输出 基于FreeRTOS开发&#xff0c;旋转编码器移植了Arduino Rotary库&#xff0c;注意这个库是GPL协议的&#xff0c;使用效果不错&#xff0c;首先奉上源码链接。 之前做过一个LED调光的项目&#xff08;https://oshwhub.com/czx951002/ChargeablePWMDim…

操作系统迁移难?Alibaba Cloud Linux 支持跨版本升级 | 龙蜥技术

背景 阿里云服务器迁移中心 SMC 操作系统迁移推出 Alibaba Cloud Linux 2 到 Alibaba Cloud Linux 3 的操作系统跨版本升级的功能。可以通过 SMC 控制台将 Alibaba Cloud Linux 2 一键原地升级为 Alibaba Cloud Linux 3。 Alibaba Cloud Linux 2 将会在 2024 年 3 月 31 日结…

ChatGPT是如何产生心智的?

一、前言 - ChatGPT真的产生心智了吗&#xff1f; 来自斯坦福大学的最新研究结论&#xff0c;一经发出就造成了学术圈的轰动&#xff0c;“原本认为是人类独有的心智理论&#xff08;Theory of Mind&#xff0c;ToM&#xff09;&#xff0c;已经出现在ChatGPT背后的AI模型上”…

ScheduledExecutorService的坑

参考文献 调度服务 ScheduledExecutorService 经常卡顿问题的排查及解决方法-腾讯云开发者社区-腾讯云 场景 一个安顿广播程序使用的ScheduledExecutorService来定时执行任务&#xff0c;当有一个任务出现异常后就会卡住&#xff0c;不会继续执行后续的任务。 解决方案 查找定…

完美解决 flex 实现一行三个,显示多行,左对齐

效果图 代码 <body><section class"content"><div class"item">元素</div><div class"item">元素</div><div class"item">元素</div><div class"item">元素</di…

121-宏免杀

CS生成宏&上线 生成宏 1.cs生成宏&#xff0c;如下图操作 2.点击复制宏代码&#xff0c;保存下来 cs上线 注&#xff1a;如下操作使用的是word&#xff0c;同样的操作也适用于Excel 1.新建一个word文档&#xff0c;使用word打开。点击文件—— 2.更多——选项—— 3.自定义…

如何自学(黑客)网络安全技术————(详细分析学习思路)方法

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…