leetcode-栈总结

本文详细解析了LeetCode上的经典栈算法题目,包括最小栈、有效括号、逆波兰表达式求值等,提供了多种解题思路,如双栈法、单栈法及迭代器实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode-155-最小栈(min stack)-java
解法1(用2个栈)
由于用常数时间得到最小值,显然要以空间换时间
设置两个stack,一个为数的stack,一个为此时min的stack
插入一个数,如果它比min的top都小,则min add 它 否则 add min的top
解法2(一个栈,一个min)
在入栈时,如果这个元素小于等于旧的最小值,那么,我们让旧的最小值入栈,然后将元素值赋给最小值,即新的最小值,然后正常将这个元素入栈;在出栈时,如果栈顶元素与最小值相等,说明他的下一个元素是之前push的旧的最小值(上一个),出栈后,将这个之前的最小值赋值给最新的最小值。(每次push进去的最小值都是下面元素的最小值)

leetcode-java-20-有效的括号(valid parentheses)-java
用栈,如果是前面的括号则直接入栈,如果是后面的先检查栈是否为空,然后看pop出的括号是否为对应的前括号,最后遍历完检查栈是否为空,若不为空,这说明有前扩或未对应
用switch和各种方法简化了流程
如何检查一个数是否在几个值之内,和是否对应另一个值,可以用map的方式进行简化和对应

leetcode-150- 逆波兰表达式求值(evaluate reverse polish notation)-java
建立一个栈,对数组进行for循环
如果是数字,则直接放入栈
如果是符号,从栈中取出两个数字,第一个取出是右边的操作数,第二个是左边的,根据符号运算出结果,再放入栈中
最后栈中仅仅剩下一个数,就是结果,取出即可

leetcode-341-扁平化嵌套列表迭代器-java
解法1
内部有一个stack,index大的先放进去,小的后放进去。next时,弹出最上面的,如果是数字,直接返回。如果不是数字,将列表从后到前依次放进stack,然后再次调用next方法。
hasNext,由于会出现stack不为空,但是NestInteger为{}的情况,需要先调用next得到返回的结果不为null,再返回true,同时把返回的结果放到nextInteger里面,next方法优先返回nextInteger,然后清空这个字段

解法2

在类中添加nestedList、stack、iteratot、integer四个属性,分别对应嵌套列表、迭代器存储栈、当前迭代器、当前遍历整数
构造函数初始化nestedList、iterator,iterator对应的就是构造参数的迭代器。
重写hasNext()函数,主要逻辑为:

当前迭代器若hasNext()为true
判断next()是否为整数,若为整数则赋值integer,返回``true`
判断next()是否为列表,则将当前迭代器暂存至stack,并更新iterator为当前列表的迭代器,递归hasNext()函数

当前迭代器若hasNext()为false且stack非空,则迭代器出栈更新为当前iterator,递归hasNext()函数
其他情况则代表,整个扁平化嵌套列表已遍历完毕,返回false

重写next()函数,迭代器的使用规则是hasNext()返回为true时调用next()函数获取下一值,再次直接返回integer(当前遍历整数)即可。

leetcode-394-字符串解码-java
本题中可能出现括号嵌套的情况,比如 2[a2[bc]],这种情况下我们可以先转化成 2[abcbc],在转化成 abcbcabcbc。我们可以把字母、数字和括号看成是独立的 TOKEN,并用栈来维护这些 TOKEN。具体的做法是,遍历这个栈:

如果当前的字符为数位,解析出一个数字(连续的多个数位)并进栈
如果当前的字符为字母或者左括号,直接进栈
如果当前的字符为右括号,开始出栈,一直到左括号出栈,出栈序列反转后拼接成一个字符串,此时取出栈顶的数字(此时栈顶一定是数字,想想为什么?),就是这个字符串应该出现的次数,我们根据这个次数和字符串构造出新的字符串并进栈

重复如上操作,最终将栈中的元素按照从栈底到栈顶的顺序拼接起来,就得到了答案。注意:这里可以用不定长数组来模拟栈操作,方便从栈底向栈顶遍历。

leetcode-739-每日温度-java
可以维护一个存储下标的单调栈,从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里,则表示尚未找到下一次温度更高的下标。
正向遍历温度列表。对于温度列表中的每个元素 T[i],如果栈为空,则直接将 i 进栈,如果栈不为空,则比较栈顶元素 prevIndex 对应的温度 T[prevIndex] 和当前温度 T[i],如果 T[i] > T[prevIndex],则将 prevIndex 移除,并将 prevIndex 对应的等待天数赋为 i - prevIndex,重复上述操作直到栈为空或者栈顶元素对应的温度小于等于当前温度,然后将 i 进栈。

为什么可以在弹栈的时候更新 ans[prevIndex] 呢?因为在这种情况下,即将进栈的 i 对应的 T[i] 一定是 T[prevIndex] 右边第一个比它大的元素,试想如果 prevIndex 和 i 有比它大的元素,假设下标为 j,那么 prevIndex 一定会在下标 j 的那一轮被弹掉。
由于单调栈满足从栈底到栈顶元素对应的温度递减,因此每次有元素进栈时,会将温度更低的元素全部移除,并更新出栈元素对应的等待天数,这样可以确保等待天数一定是最小的。

剑指offer-7-用两个栈实现队列-java
stack1为栈,都插入到stack1的中,如果要删除头部,把stack1的元素一个个放到stack2中,相当于原来stack1的栈顶为尾部,现在stack2的栈顶为头部,删除stack2的栈顶即可。如果stack2没有元素删除了,再次把stack1倒入stack2

剑指offer-21-包含min函数的栈-java
首先这个栈要具有普通栈所具有的push()和pop()方法,那么内部一定包含一个Stack。至于还要能实现min函数,而且还是在O(1)时间复杂度内,我们不得不考虑用额外的空间。

如果直接使用一个int变量存储当前的最小值,我们的确可以获得最小值,但是当栈pop()了以后,我们无法获得次小值。我们需要一个数据结构来动态保存每个时刻的最小值,每当push()和pop()的时候,同样更新这个数据结构,而且时间复杂度也是O(1),那么看来需要额外O(n)的空间了。可以选择栈或者一个链表(实质上当作栈使用)。我们使用一个辅助栈来实现,该栈和主栈的大小相同,栈顶存放的是当前栈内的最小值。

剑指offer-22-栈的压入、弹出序列-java
创建一个辅助的堆栈,定义一个指向弹出序列第一位的指针,对于压入序列,每个数压入辅助栈中,每当压入一个数进行判断:栈顶元素与弹出序列指针所指的数进行比较,若相同则弹栈,同时指针后移一位,直到栈顶元素与指针所指元素不同,则压入下一个压入序列中的数。最终若辅助栈为空说明弹出序列为压入序列的弹出顺序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值