栈及经典问题(一)

一、栈的基础知识

栈是⼀种“先进后出”(FILO, First In Last Out)的数据结构。

二、经典面试题

1.栈的基本操作

LeetCode #面试题03.04 化栈为队

利⽤两个栈来实现,⼀个输⼊栈、⼀个输出栈。

输⼊栈⽤于读⼊数据。当需要输出元素时,若输出栈为空,则将输⼊栈的所有元素 推送到输出栈,然后取栈顶元素;若输出栈⾮空,则输出栈顶即可。

输出栈的作⽤是对已经被反转的序列进⾏⼆次反转。对此感到困惑的同学可以画图模拟⼀下。

LeetCode #844 比较含退格的字符串

按照题意实现即可。

LeetCode #946 验证栈序列

被出栈的元素只有两种可能:即将⼊栈的元素 和 当前栈顶的元素。

只需要关注出栈序列,分类讨论后模拟即可。

2.栈结构扩展应用

LeetCode #20 有效的括号

结论1:在任意⼀个位置上,左括号数量>=右括号数量

结论2:在最后⼀个位置上,左括号数量==右括号数量

根据上述两个结论,程序中只需要记录左括号和右括号的数量即可。

⼀对括号可以等价为⼀个完整的事件。左括号可以看作事件的开始、右括号可以看

作事件的结束。⽽括号序列可以看作事件与事件之间的完全包含关系。

栈可以处理具有完全包含关系的问题。

LeetCode #1021 删除最外层的括号

左括号和右括号差值为0时,代表这⼀串括号序列是独⽴的,可以被单独分解出来。

LeetCode #1249 移除⽆效的括号

可以被匹配的括号都是有效的,⽽其他的括号都需要被删除。

LeetCode #145 ⼆叉树的后序遍历

递归做法⽐较简单,在这⾥介绍⼀下基于迭代的做法。

技巧是使⽤两个栈,⼀个数据栈,⼀个状态栈。将“遍历左⼦树”,“遍历右⼦树”和“访问根节点”三个步骤分别⽤状态码表⽰,枚举状态转移过程,使⽤有限状态⾃动机(FSM, Finite State Machine)的模型来模拟递归过程。

LeetCode #331 验证⼆叉树的前序序列化

思路1:每次拆掉⼀个“数字、#、#”的节点(即叶⼦结点),最后树上的全部节点都会被拆光(即只剩⼀个“#”),能拆光的序列就是合法序列。

思路2:初始状态有⼀个坑。每多增加⼀个数字节点,会在占掉⼀个坑后,产⽣两个坑,每多增加⼀个#,会减少⼀个坑。合法的⼆叉树前序遍历最后会刚好⽤完所有的坑。

LeetCode #227 基本计算器II

思路1:找到式⼦中优先级最低的运算符,然后递归分治运算两侧的⼦式即可。

思路2:使⽤操作数栈和操作符栈辅助计算,当操作符栈遇到更低优先级的操作符时,需要将之前更⾼级别的操作符对应的结果计算出来。

对于有括号的情况,左括号相当于提⾼了内部全部运算符的优先级,当遇到右括号的时候需要将匹配的括号间的内容全部计算出来。

可以通过加⼀个特殊操作符的处理技巧,来额外处理结尾的数字。

智力发散题

LeetCode #636 函数的独占时间

本质就是⼀道模拟题,画⼀个线段图能显著地辅助理解。任务开始时进栈,上⼀个任务暂停执⾏;任务完成时出栈,恢复上⼀个任务的执⾏。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fzshuai25

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值