栈和队列OJ题详解

一.有效的括号:

20. 有效的括号 - 力扣(LeetCode)

首先拿到这个题目,我的第一个思路是利用双指针来走,看看是不是匹配的

但是这种情况就把双指针的这个思路直接pass了,明明是匹配的括号,用双指针一走就不是匹配的。所以这个思路直接pass。

还有一个思路就是用栈来解决问题,如果是左括号就入栈,如果是右括号就与出栈顶的左括号看看是不是匹配的。

是左括号就入栈

是右括号就让栈顶的左括号出栈顶,看看两个是否匹配,就这样一个个匹配,如果都匹配上了,就是有效括号

这就是一个整体的思路,这就利用了栈的后进先出,这就可以找到离右括号最近的左括号进行匹配。所以是左括号入栈,右括号和栈顶的左括号去匹配如果匹配上了,就继续。

思路就是这么个思路,现在来实现代码:

首先把我们写过的栈的实现copy过来

再创建一个栈来存放左括号,创建完再初始化一下:

接下来再判断是否为左括号,是就入栈,是右括号就去栈顶的数据与其看看是否匹配:

在else语句里就是考虑是右括号的情况,但是如果我们写的代码是左括号与右括号匹配的话,只匹配一次并没有什么效果,要全部遍历完匹配才是真正的匹配,所以我们这里是写左括号与右括号不匹配的情况:

这里入栈是特别多的情况有可能边入边出,也有可能,先入几个,再出几个,情况复杂,所以用栈来实现这些复杂的情况,这样就可以找到最近的左括号是否与右括号相匹配。

接下来我们运行一下:

发现这个用例没有通过,发现在栈里面还有左括号没有出来,还有一种情况:

如果是这种情况,前面的括号都匹配成功,但是发现栈顶里面还有数据,但按照上面的代码此时任然会返回true,所以这次是数量没有对上,我们在这里还要加一个栈的判空,如果栈里面还有数据那么肯定是false。

此时加了这种情况我们再来运行代码:

此时我们发现如果只有一个右括号的话,我们去取栈顶数据,此时栈顶为空,这里取的话就是对空指针的解引用就会报错。

现在加上这种情况,再来测试:

完美通过了。

整个代码如图:

二.用队列实现栈:

225. 用队列实现栈 - 力扣(LeetCode)

栈是后进先出,而队列是先进先出

比如说这两个队列,一个队列里存着1 1 2,现在要实现栈就是取出栈顶数据2,怎么操作呢,先把1 1拿去另一个空的队列,然后再把2拿出来。

现在3要入栈那么就是入不为空的队列

再想去栈顶数据还是先将 1 1出队列再把3取出来。

现在来实现代码:

首先还是把我们实现队列的功能拷贝过来。

然后栈的创建就是开辟一个给栈的内存空间,然后调用写好的队列初始化函数,这样栈的创建就写好了。

现在来实现入栈:

上面也介绍过了,这里入数据是入队列是入不为空的队列,所以这里要利用判空函数,看看数据存在哪里:

谁不为空就存在哪里。

现在来实现移除栈顶元素并返回函数:

这里还是跟上面一样,有数据的队列就先移动size-1的数到另一个空的队列 然后就返回剩下的那个值即可。

这里还是用到假设法,假设一个队列为空进行操作,不为空就换一下就行,这样省下了很多代码。

这就是假设法的完成。

现在来完成具体操作,就是将不为空的队列的前size-1的数据取出,导给为空的队列,一开始不为空的队列现在就剩下一个数据,那个数据就是栈顶元素。

这就是整个的实现过程。

现在来实现返回栈顶元素的函数:

实现队列的时候,我们完成了取出队尾的数据的函数,在这里只要判断一下哪个队列不为空,就利用这个函数去取出栈顶元素即可:

现在来实现对栈的判空:

这个就是对两个队列进行判空,如果两个队列都为空,则这个栈必定是空的,如果有一个不是,则栈就不为空。

现在来实现对栈的销毁:

这里就是利用封装好的对队列销毁的函数,销毁两个队列,并且释放掉开辟的空间即可。

前面队列的实现是之前写好的,而此题中我们写的部分的代码如图:

整个代码如图:

三.设计循环队列:

622. 设计循环队列 - 力扣(LeetCode)

这里用数组去实现这个循环队列。

先在要实现循环队列的结构体里,先定义一个整型指针变量来存放开辟的空间再定义head和tail的变量,这样方便后面找尾和找头时直接利用。还有题目要求的队列长度变量k。

还有一个值得注意的是tail指的是队尾数据的下一个,如果tail指向队尾,那么空的时候指向的那个位置,一个数据指向的也是那个位置,所以这样就区分不开。所以这里tail指向的是队尾数据的下一个。

这里想删除数据,怎么删除呢?

就是head++,然后给那个数据给占掉。

这里再插入数据3:

这里tail指向的是队列结尾的下一个位置,因为是循环队列所以就绕回来了。

所以在这里就是有限的空间,保证先进先出,重复使用来实现循环队列。

但是我们还要考虑几个问题什么时候为空,什么时候为满?

第一种就是head==tail时为空。

那什么时候为满呢?

当tail和head从第二个空开始时,不断插入数据,最后发现还是tail==head时是满的,所以当head==tail时不知道是空还是满的情况,所以我们在这里要解决一下这个问题。

方法一:利用size来记录一下,当size==k时就是满,size==0即为空。

方法二:额外多开一个空间,就是开k+1的空间。

方法二比较装所以我们用方法二来解决,上图我们是能存放3个数据,我们利用方法二再额外多开一个空间,但这个空间不能用来存放数据,只能用来判断是空还是满来使用的。

如图:

我们在这里放入了三个数据,但是已经满了,这里我们再删除两个数据:

此时再插入两个数据看看:

此时就不能再插入了,再插入就溢出了,因为虽然是额外开的空间,但是存储的数据个数还是k个所以在这里用额外开辟空间的方法就有效避免了head==tail时有可能即为空也为满的情况,所以在这里tail+1==head即为满,tail==head即为空。

但其实并不是这么简单还有一种情况:

这种情况队列也满了,但是tail+1!=head所以这里我们用到了一个非常巧妙的运算(tail+1)%(k+1)==head即为满,比如说这里k==3,tail==3,所以一模就是0,这里head=0,所以为满,因为这里是数组,所以下标特殊。

再考虑上面那种情况,k==3,tail==1,所以(tail+1)%(k+1)==2,此时head=2,所以为满,这个模的运算非常巧妙的将所有情况全部包括进去了。

综上所有的分析,现在我们来实现代码:

首先就是循环队列的创造:

再来实现循环队列的判空,根据上面的分析,如果head==tail即为空:

再来实现循环队列的判满,也就像上面分析的那样利用模运算来判断:

再来实现向循环队列插入一个元素。如果成功插入则返回真:

模一下的意义就是防止这个情况的出现,此时再来一个数据当出现这样的情况模一下,解决了回绕的问题。比如4%4=0这样tail就又回到了头的位置。

再来实现从循环队列中删除一个元素。如果成功删除则返回真:

这个模的情况也是解决回绕的问题。

再来实现从队首获取元素。如果队列为空,返回 -1 :

再来实现获取队尾元素。如果队列为空,返回 -1 :

利用三目运算符,如果tail在数组的头,就返回数组的尾,如果不是,tail指的是队尾的下一个数据,所以返回tail-1处的数据即可。

整个代码如图:

四.用栈实现队列:

232. 用栈实现队列 - 力扣(LeetCode)

要实现之前,栈是后进先出,队列是先进先出。

假设数据是1 1 2,现在想要出队列,就是出1,但是栈是后进先出,栈只能出2:

所以我们先把数据导到另一个栈里面去,然后顺序就是变成2 1 1,让他出栈就行:

然后现在想要入数据,比如说入3,这里又要怎么做呢:

这里我们可以直接放入另一个栈:

现在又想出数据了,因为是队列原本的顺序是1 1 2所以出的还是1,这样直接出2 和 1那个栈的数据就行,不用导过来导过去的了.

综上,我们可以定义两个栈,一个栈用来是入栈的,另一个是用来出栈的。

现在来实现队列的创造:

先开辟一个结构体指针的空间,然后再利用封装好的栈的初始化函数来初始化就行。

现在来实现将元素 x 推到队列的末尾:

这个功能简单的来说就是入栈,我们前面的思路已经讲过有数据直接放入专门入栈的栈中即可。

现在来实现返回队列开头的元素:

先全都将入栈的数据导到出栈的栈中,然后返回栈顶元素即可:

如果出栈的栈是空的,就将入栈的栈的数据导过来,如果不为空直接返回出栈的栈的栈顶元素即可。

 现在来实现从队列的开头移除并返回元素:

有了上一个函数的基础,这个就非常简单了,调用上一个函数,再将出栈的栈的栈顶数据删除即可:

现在来实现队列的判空:

还是对两个栈进行判空,如果都为空则队列也为空

现在来实现队列的销毁:

也就是销毁两个栈,再释放掉开辟的空间:

实现栈的功能的代码如图:

整个代码如图:

总结:这就是几个关于栈和队列的OJ题整个分析过程。

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

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

相关文章

1.3 Windows 的 CLion 开发环境安装

目录 1 C 语言的那些事 2 开发环境安装及新建项目 2.1 安装 MinGW 编译器 2.2 安装 CLion 开发环境

Android Audio基础——AudioFlinger回放录制线程(七)

AndioFlinger 作为 Android 的音频系统引擎,重任之一是负责输入输出流设备的管理及音频流数据的处理传输,这是由回放线程 PlaybackThread 及其派生的子类和录制线程 RecordThread 进行的。 一、基础介绍 1、关系图 ThreadBase:PlaybackThread 和 RecordThread 的基类。 Re…

人工智能最新的新闻动态

一、AI交互内容创新国际竞赛启动 主办单位:南京市科协启动时间:2024年5月26日目的与意义:鼓励全球科技人才参与AI创新,拓宽南京与海外科技人才的交流渠道,注入国际化活力,推动AI技术创新应用,挖…

react diff 原理

React的Diff算法(也称为React Diff原理或React Diffing策略)是React框架中用于优化DOM更新的核心机制。其核心思想是通过比较新旧Virtual DOM的差异,仅更新有变化的部分,以提高渲染效率。以下是React Diff算法的主要原理和策略&am…

【linux】多线程(2)

文章目录 线程的应用生产消费者模型自制锁生产消费队列成员参数生产函数消费函数 任务处理方式主函数 POSIX信号量sem_wait()sem_post() 线程池应用场景示例 单例模式饿汉实现单例 吃完饭, 立刻洗碗, 这种就是饿汉方式. 因为下一顿吃的时候可以立刻拿着碗就能吃饭.懒汉实现单例…

visual studio code生成代码模板

编写需要生成代码片段的代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…

【C++】二分查找算法:x的平方根

1.题目 2.算法思路 看到题目可能不容易想到二分查找。 这题考察我们对算法的熟练程度。 二分查找的特点&#xff1a;数组具有二段性(不一定有序)。 题目中没有数组&#xff0c;我们可以造一个从0到x的数组&#xff0c;然后利用二分查找找到对应的值即可。 3.代码 class S…

ionic关于@angular版本报错解决方案(有效)

最近学校要求使用ionicangular学习&#xff0c;但是出现下面问题&#xff0c;这里我就分享一个我亲测有效的解决方案&#xff0c;提供学习&#xff08;在VScode中&#xff09; npm error code ERESOLVE npm error ERESOLVE could not resolve npm error npm error While resol…

C语言生成正弦波测试数据易懂版本

以往生成正弦波数据, 各个参数之间的关系总是不明确, 现在这个函数的代码非常明确的区分了各个参数之间的相互关系. #include <stdio.h> #include <math.h>/*** brief 生成正弦波测试数据* * param data 存放生成的数据的数组* param n 数据的长度 一共采样了多少…

源码编译安装LAMP(安装apeche mysql php 论坛 网站 巨详细版)

目录 一.LAMP架构相关概述 1.各组件作用 Linux&#xff08;平台&#xff09; Apache&#xff08;前台&#xff09; MySQL&#xff08;后台&#xff09; PHP/Perl/Python&#xff08;中间连接&#xff09; 总结 二.编译安装Apache httpd服务 1.关闭防火墙&#xff0c;将…

解决SpringBoot中插入汉字变成?(一秒解决)

在这里url后面加一行配置即可&useUnicodetrue&characterEncodingUTF-8即可 解释 spring.datasource.url: 这里包含了数据库的URL&#xff0c;以及额外的参数如useUnicodetrue用于启用Unicode字符集支持&#xff0c;characterEncodingUTF-8用于指定字符编码为UTF-8&…

Java面向对象-常用类(Math类)

常用类-Math类 Math 类提供了一序列基本数学运算和几何函数的方法。 Math类是类&#xff0c;并且它的所有成员变量和成员方法都是静态的。 1 Math类的常量和常用方法 常量 static doubleE 比任何其他值都更接近 e&#xff08;即自然对数的底数&#xff09;的 double 值。stati…

什么是SPI,和API有啥区别

Java 中区分 API 和 SPI&#xff0c;通俗的讲&#xff1a;API 和 SPI 都是相对的概念&#xff0c;他们的差别只在语义上&#xff0c;API 直接被应用开发人员使用&#xff0c;SPI 被框架扩展人员使用。 API (Application Programming Interface) 定义: API是一组定义了软件组件…

图像处理ASIC设计方法 笔记24 等价表和标记代换

&#xff08;一&#xff09;等价表的整理与压缩 1.1 等价关系的识别与追踪 在初步标记过程完成后&#xff0c;等价表的整理和压缩变得至关重要。这一阶段的首要任务是从等价表的地址1开始&#xff0c;对等价表进行逐个扫描。在扫描过程中&#xff0c;系统将检查每个临时标记是否…

链表类型的无界阻塞线程安全队列-ConcurrentLinkedQueue(FIFO)

ConcurrentLinkedQueue是非阻塞线程安全(volatile不能完全保证线程安全)的队列,适用于“高并发”的场景。是一个基于链表节点的无界线程安全队列,按照 FIFO(先进先出,尾先进头先出)原则对元素进行排序。队列元素中不可以放置null元素(内部实现的特殊节点除外)。 volati…

【rust工具链】

1 查看正在使用的工具链 命令&#xff1a;rustup show 结果显示&#xff1a; 从图中可以看到正在使用的是rustc 1.76.0版本&#xff0c;也可以看到已安装的所有版本的工具链 2 使用默认工具链 命令&#xff1a;rustup default 版本号 例如&#xff1a;rustup default 1.58…

【重学C语言】十五、文件操作

【重学C语言】十五、文件操作 文件的概念什么是流文件类型文本文件和二进制文件的区别文件指针文件指针常量预定义的文件指针stdin (标准输入)stdout (标准输出)stderr (标准错误输出)示例文件指针的声明使用文件指针悬挂指针示例文件缓冲区为什么需要缓冲区?缓冲区的类型缓冲…

Python语言绘制好看的小提琴图、箱形图、散点图、山脊图和柱状图等等

废话不多说&#xff0c;今天给大家分享一个&#xff0c;使用python绘制小提琴图、箱形图、散点图、山脊图和柱状图等等 图中的数据是随机生成的&#xff0c;图例&#xff0c;图注以及坐标题目各种信息&#xff0c;具体内容大家可以自己修改~ 效果图如下所示 &#x1f447;&a…

AIGC时代算法工程师的面试秘籍(2024.4.29-5.12第十三式) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试方法&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

『ZJUBCA Weekly Feed 07』MEV | AO超并行计算机 | Eigen layer AVS生态

一文读懂MEV&#xff1a;区块链的黑暗森林法则 01 &#x1f4a1;TL;DR 这篇文章介绍了区块链中的最大可提取价值&#xff08;MEV&#xff09;概念&#xff0c;MEV 让矿工和验证者通过抢先交易、尾随交易和三明治攻击等手段获利&#xff0c;但也导致网络拥堵和交易费用增加。为了…