剑指 Offer 31. 栈的压入、弹出序列 - leetcode 剑指offer系列
发布日期:2021-06-29 07:12:07
浏览次数:3
分类:技术文章
本文共 2563 字,大约阅读时间需要 8 分钟。
题目难度: 中等
今天继续更新剑指 offer 系列, 这道题挺有意思的, 需要反其而行之, 这里依然提供两种方案供大家参考, 特别是方法 2, 对空间复杂度做了优化, 值得一读
老样子晚上 6 点 45 分准时更新公众号 每日精选算法题, 大家记得关注哦~ 另外在公众号里回复 offer 就能看到剑指 offer 系列当前连载的所有文章了
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
- 0 <= pushed.length == popped.length <= 1000
- 0 <= pushed[i], popped[i] < 1000
- pushed 是 popped 的排列。
题目样例
示例 1
输入
pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出
true
解释
我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4, push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1示例 2
输入
pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出
false
解释
1 不能在 2 之前弹出。
题目思考
- 直接模拟整个过程可行吗?
- 有没有不使用额外空间的做法?
解决方案
方案 1
思路
- 我们可以尝试使用一个栈模拟整个过程, 看看模拟过程中能否满足两个序列的顺序
- 对于每个压入序列, 我们直接将其压入栈中
- 而对于弹出序列, 我们需要额外维护一个指针, 指向当前要弹出的元素下标, 显然该指针初始化为 0
- 接下来比较栈顶是否和当前指针指向的元素是否相同, 相同的话弹出并让指针后移一位
- 重复上述过程直到遍历完整个压入序列
- 那么如果两个序列匹配的话, 最终的栈应该为空的.
- 注意这里无需判断弹出序列是否也遍历完(即指针指向最后一个元素后一位), 因为如果栈为空的话代表每个 push 都对应一个 pop, 而两个序列长度相等, 所以此时弹出序列肯定也遍历完了.
- 而如果最终的栈不为空, 则说明弹出序列不对了, 卡在了某个下标处, 本应该先弹当前栈顶的, 结果弹出序列的当前元素不是栈顶, 无法正常弹出.
复杂度
- 时间复杂度
O(N)
- 每个元素只会被压入和弹出栈一次
- 空间复杂度
O(N)
- 额外需要一个栈
代码
class Solution: def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool: # 方法1: 利用栈模拟, 额外使用一个指针存储当前弹出序列位置 stack = [] j = 0 for p in pushed: stack.append(p) while stack and j < len(popped) and stack[-1] == popped[j]: # 当前栈顶恰好等于当前弹出序列对应的元素, 栈弹出, 指针后移 stack.pop() j += 1 # 如果栈为空则说明这两个序列有效 return not stack
方案 2
思路
- 回顾方案 1, 我们需要额外一个栈来老老实实模拟整个过程, 有没有不需要额外空间的做法呢?
- 答案也是肯定的, 方案 1 中的栈的目的就是模拟压入弹出过程, 整个遍历一遍压入队列, 我们其实可以直接利用压入队列来作为这个栈, 然后栈顶就用新的一个指针来代替即可, 这样就不需要额外空间了
- 其他思路和方案 1 相同, 入栈相当于当前压入队列指针的赋值+后移, 而出栈则简单的等同于压入队列指针的前移
- 最终就是判断栈顶指针是否为-1 来判断栈是不是空
复杂度
- 时间复杂度
O(N)
- 每个元素只会被压入和弹出栈一次
- 空间复杂度
O(1)
- 使用常数个变量
代码
class Solution: def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool: # 方法2: O(1)空间, 将pushed本身当作栈, 用一个下标表示当前栈顶, 双指针 topindex, j = -1, 0 for i in range(len(pushed)): # 压入新元素, 所以需要先将栈顶指针后移一位, 然后赋值 topindex += 1 pushed[topindex] = pushed[i] while j < len(popped) and topindex >= 0 and pushed[ topindex] == popped[j]: # 当前栈顶恰好等于当前弹出序列对应的元素, 栈顶指针前移, 弹出队列指针后移 topindex -= 1 j += 1 # 如果栈顶指针为-1, 说明栈为空, 也即这两个序列有效 return topindex == -1
大家可以在下面这些地方找到我~😊
我的公众号: 每日精选算法题, 欢迎大家扫码关注~😊
转载地址:https://blog.csdn.net/zjulyx1993/article/details/107344897 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2024年04月01日 16时04分34秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
find 命令特点及用法
2019-04-29
python实例018--验证爬下来的代理ip是否可用,去掉不可用的代理
2019-04-29
python实例019--爬取网站时的图片
2019-04-29
python实例020--爬取图片网站上的原图作为壁纸
2019-04-29
python实例021--利用python判断一个数是奇数还是偶数
2019-04-29
POJ 2481 Cows 树状数组 单点更新 (每个集合是几个集合的真子集)
2019-04-29
POJ 2482 线段树 离散化 扫描线 矩阵最大权值
2019-04-29
传奇游戏源码下载
2019-04-29
egret农场游戏源码
2019-04-29
当爱你的人不再爱你了,还有AI“安慰”你
2019-04-29
100%识别差评!用AI听懂网购者的“言外之意”
2019-04-29
第八期“AI未来说·青年学术论坛”带你入门深度学习
2019-04-29
除了程序猿,开发人员还是设计师、建筑师……
2019-04-29
一个优秀技术经理必备的30条“软实力”,你有吗?
2019-04-29
从市场营销到程序开发,跨界的黄金法则有哪些?
2019-04-29
NLP入门第一步:6种独特的数据标记方式
2019-04-29
如何通过9个月的学习,得到机器学习职位?
2019-04-29
AI电影修复技术,带回《乱世佳人》高清版斯嘉丽
2019-04-29
中科院-百度联合造AI精品课程,0元你还不心动!
2019-04-29