代码随想录算法训练营day10~day13栈与队列No.232 225 20 1047 150 239 347

本文介绍了如何用栈和队列实现队列和栈的功能,以及在C++和JavaScript中处理字符串操作(如有效括号、删除相邻重复项和逆波兰表达式求值)、滑动窗口问题和找到前k个高频元素的方法,重点讨论了优先级队列和单调队列在这些问题中的应用。

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

day10

理论基础

学过js数据结构,这一部分关于c++的直接略过

232.用栈实现队列

题目链接
说明:
你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

讲解
因为栈是先进后出,队列先进先出,就是用两个栈完成一个元素的反转:判断出栈为控,入栈不为空;然后将所有的元素放到出栈里,再取出来;注意需要把所有元素都放到出栈,否则若有新增元素,顺序就会乱。
代码

225. 用队列实现栈

题目链接
使用队列实现栈的下列操作:

push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空
注意:
你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)

讲解
一个队列模拟栈(视频):
将队列里除了最后一个元素(size-1个)都弹出,重新放入队列里,就能弹出最后一个元素了。
获取栈顶元素就是队列入栈的最后一个元素(que.back)js需要看有没有对应的函数实现
两个队列模拟栈
代码


day11

20. 有效的括号

题目链接
讲解
由于栈结构的特殊性,非常适合做对称匹配类的题目。
题意其实就像我们在写代码的过程中,要求括号的顺序是一样的,有左括号,相应的位置必须要有右括号。
实际上只有三种情况:

  1. 左边括号多了
  2. 括号类型不匹配
  3. 右边括号多了

思路就是遍历字符串时遇到左括号,拿一个栈储存对应类型的右括号;直到遍历到右括号,开始拿字符串中的右括号与栈顶元素进行匹配(这里就是遍历左括号储存右括号的好处,不用写额外的逻辑匹配,直接消消乐就行),相同就删除这个元素,去遍历下一个括号;若出现栈为空||不匹配,返回false;栈为空说明右括号多了情况3,不匹配情况2;情况1就是字符串遍历结束栈里还有元素。
剪枝:字符串为奇数直接返回false
代码

1047. 删除字符串中的所有相邻重复项

题目链接
讲解
可以定义一个字符串来模拟栈,这样最后结果就不用转换了,只要注意字符串的头部和尾部,需要对应正确的字符串顺序。
栈为空或遍历元素与栈顶不相等时放入栈里;
遍历一个,放入栈,第二个的时候与栈顶元素匹配,不匹配就放入继续重复;如果匹配就消除,然后往下一边遍历,一边匹配栈顶元素,到最后取出正确顺序的字符串(字符串模拟可以直接得到)

递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

相信大家应该遇到过一种错误就是栈溢出,系统输出的异常是Segmentation fault(当然不是所有的Segmentation fault 都是栈溢出导致的) ,如果你使用了递归,就要想一想是不是无限递归了,那么系统调用栈就会溢出。
在这里插入图片描述

代码

150. 逆波兰表达式求值

题目链接
讲解
中序表达式就是正常的算式;
后序(后缀)表达式是左右中;是计算机运算时使用的方式;不需要给加减运算加括号,只要按顺序遍历就能得到正确结果;
用栈来计算:遇到数字存到栈里;遇到操作符就取出栈头两个数字进行运算(二叉树),然后把结果放到栈里。
其实也是消除:两个元素遇到操作符就消除了。
题目中说的逆波兰表达式没有异常的表达,所以不用考虑异常
代码


day12休息
day13

239. 滑动窗口最大值

题目链接
讲解
大顶堆无法保证弹出的值一定是对的,因为顺序会变会变成从大到小,在往后移动时就无法确定谁是应该弹出去的元素;
但单调队列(单调递增或单调递减)可以自己定义怎么弹出元素;
这道题目需要实现的是这三个函数:弹出之前的元素,压入下一个元素,每次移动判断哪个是最大值;
pop和push都需要判断队列非空
思路
没必要维护三个元素;只需要把最大值放在队列出口;
push元素的时候,如果比队列入口元素大,就可以把之前的元素都卷走不用维护,比入口元素小的就成为新的入口元素(后续当最大值被弹出时也可能成为新的最大值,所以要留下,再新加入元素时如果比出口小但是比队列里其他元素大,就把其他元素卷走,排在最大值后面),出口元素就是最大值;
pop的时候如果要pop的元素与最大值(队列出口)相等,就需要把队列出口pop出去(1.弹走了所以不是最大值了,队列出口不能是它了2.因为之前不是最大值的元素push新元素时已经被卷走了没有实际执行pop操作)。
js的不同之处:
在这里插入图片描述
dq的出口(front)和入口(back)都可以实现出元素和入元素
题解中单调队列里的pop和push接口,仅适用于本题哈。单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。 不要以为本题中的单调队列实现就是固定的写法
代码

347.前 K 个高频元素

题目链接
讲解
快排算法时间复杂度是O(nlogn)?
大顶堆是根节点是最大的元素;小顶堆是根节点是最小的元素
用堆遍历map(key元素,value出现频率)里的所有元素
只维护k次的元素。
堆是一种二叉树结构;
用大顶堆时,push元素会把堆顶,即二叉树根节点即最大的元素弹出去(最大的:k次的值),所以剩下的是前k个低频元素。
所以用小顶堆。
时间复杂度,大/小顶堆遍历一边是n,在堆中加入一个元素是logk(维护k个元素,只对k个元素进行排序)。所以是O(nlogk)优于nlogn
需要实现compare函数。
代码

总结

优先级队列和单调队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值