Leetcode:622. 设计循环队列 题解【具详细】
目录
一、题目:
二、思路详解:
1.循环队列的存储定义
2.循环队列的创建
3.循环队列的判空与判断情况
(1) 循环队列的判空:
(2) 循环队列的判满
4.循环队列元素的插入
5.循环队列元素的删除
6.获取队头元素
7.获取队尾元素
8.循环队列释放
三、完整代码展示:
一、题目:
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。Front: 从队首获取元素。如果队列为空,返回 -1 。Rear: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty(): 检查循环队列是否为空。isFull(): 检查循环队列是否已满。难度:中等
题目链接:622. 设计循环队列
示例:
MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3 circularQueue.enQueue(1); // 返回 true circularQueue.enQueue(2); // 返回 true circularQueue.enQueue(3); // 返回 true circularQueue.enQueue(4); // 返回 false,队列已满 circularQueue.Rear(); // 返回 3 circularQueue.isFull(); // 返回 true circularQueue.deQueue(); // 返回 true circularQueue.enQueue(4); // 返回 true circularQueue.Rear(); // 返回 4
题目解析:就是根据题中给的接口进行函数的实现。要求我们实现一个循环队列。
用心阅读下方会有很大的收获。

二、思路详解:
1.循环队列的存储定义
首先我们需要定义出一个循环队列的存储定义,这里采用的是使用动态数组来进行模拟循环队列,根据题中给出的接口返回类型,我们可以知道循环队列的数据类型为int 。
其次,还需定义两个记录数组的下标,一个记录队列的队头,另一个记录队列的队尾(也就是指向要入队的下一个元素的位置)。另外还要提供一个表示要存储数据的具体个数。
如图:

代码:
//采用动态数组的形式来模拟循环队列
typedef struct {int* a; //指向数组int front; //队头int tail; //队尾int k; //数据个数
} MyCircularQueue;
2.循环队列的创建
循环队列的创建,先使用malloc进行创建一个 循环队列空间
接着根据给的数据个数k让指针a指向一个动态数组,在分别对front,tail,k进行初始化,注意tail = 0表示要存放的下一个数据元素的位置,对动态数组a开辟空间的时候要多开辟一个空间,避免假溢出的现象。最后一定要返回之前创建的循环队列。
代码:
//创建长度为k的循环队列
MyCircularQueue* myCircularQueueCreate(int k) {//使用动态内存函数来申请内存//这里多申请一个空间的目的是防止假溢出//使用malloc创建一个循环队列MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//为循环队列里面的指针a ,让a指向一个长度为k+1的数组obj->a= (int*)malloc(sizeof(int)*(k+1));obj->front = 0; //队头从数组的下标0开始obj->tail = 0; //队尾指向下一个元素obj->k = k; //队列的长度为kreturn obj;
}
物理存储情况,如图:

但是我们一般会到其循环的逻辑结构,逻辑存储,如图:

3.循环队列的判空与判断情况
循环队列的插入和删除是不可避免的,当这之前就需要先完成判和判满的接口。注意:一定要把判空和判满的函数实现放在队列插入和删除函数实现的前面。
(1) 循环队列的判空:
根据函数的返回类型是bool,空我们就返回true ,否则返回false。
isEmpty(): 检查循环队列是否为空。
因为这里采取的是通过动态数组来模拟循环队列,所以队列空的条件就是当front == tail 的时候,此时的循环队列就是空的。
如图:

代码:
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空,就是队头与队尾相同时return obj->front == obj->tail;
}
(2) 循环队列的判满
同样根据函数的返回类型是bool,空我们就返回true ,否则返回false。
isFull(): 检查循环队列是否已满。
什么时候会满呢?当(tail+1)%(k+1) == front,就是队尾下标加1模开辟空间的个数
可能很多会对为什么要多开辟一个空间,原因就在这:对于队列的判满的情况,
当没有创建的额外空间,队列只有数据10 和 11 的情况下,

像上图就是假溢出现象,这个队列并没有满。
总的来说:
循环队列为了区分队列的空和满,需要额外增加一个空的元素来占据队列的一个位置,这样队列满的状态就可以通过头尾指针相邻且不重合来判断,而不会出现头尾指针重合但队列实际上并不满的情况。同时循环队列需要对头尾指针进行模运算,如果没有额外的空间,那么当队列最后一个元素占据了数组最后一个位置时,下一个元素就会从数组的第一个位置开始,这样就无法正确进行模运算,而增加一个空的元素可以解决这个问题。
代码:
bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->tail+1)%(obj->k+1) == obj->front;
}

4.循环队列元素的插入
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
插入前判断是否满,满就返回false,接着就是数据的插入,插入后,对tail下标进行取模(因为是反复利用原来的空间,还有就是避免溢出),插入成功就返回true。
代码:
//插入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//插入元素前先进行判断是否满if(myCircularQueueIsFull(obj)){return false;}//插入元素使用尾插obj->a[obj->tail] = value;obj->tail++;//避免tail的下标越界obj->tail%=(obj->k+1);return true;
}
5.循环队列元素的删除
删除前,要进行判断是否为空。队头减一,进行删除,删除后取模。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
代码:
//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//删除元素队列不能为空if(myCircularQueueIsEmpty(obj)){return false;}//出队,头删obj->front++;obj->front%=(obj->k+1);return true;
}
6.获取队头元素
获取前进行判断,是否为空。
Front: 从队首获取元素。如果队列为空,返回 -1
代码:
//获取队首元素
int myCircularQueueFront(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}return obj->a[obj->front];
}
7.获取队尾元素
获取前进行判断,是否为空。
Rear: 获取队尾元素。如果队列为空,返回 -1
代码:
//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}//注意当tail = 0的情况return obj->a[(obj->tail - 1+ obj->k+1)%(obj->k+1)];
}
解释一下 上述最后一行代码:
重点:
首先tail是指向要存放下一个元素的位置,找队尾元素时,tail要进行-1。
因为数组下标最小是从0开始的,当tail ==0且队列不为空的情况下,上方代码obj->tail-1,就会造成0-1 == -1的情况。上方采用(obj->tail - 1+ obj->k+1)%(obj->k+1)就可以完美的避免,当然
其实可以写成
int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;// return obj->a[(obj->tail-1 + obj->k+1)%(obj->k+1)];if(obj->tail == 0){return obj->a[obj->k];}else{return obj->a[obj->tail-1];}
}
8.循环队列释放
因为用malloc开辟的动态内存空间,为了避免内存泄漏,我们还要释放内存。注意释放的顺序。
代码:
void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}
三、完整代码展示:
代码:
//采用动态数组的形式来模拟循环队列
typedef struct {int* a; //指向数组int front; //队头int tail; //队尾int k; //数据个数
} MyCircularQueue;//创建长度为k的循环队列
MyCircularQueue* myCircularQueueCreate(int k) {//使用动态内存函数来申请内存//这里多申请一个空间的目的是防止假溢出//使用malloc创建一个循环队列MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//为循环队列里面的指针a ,让a指向一个长度为k+1的数组obj->a= (int*)malloc(sizeof(int)*(k+1));obj->front = 0; //队头从数组的下标0开始obj->tail = 0; //队尾指向下一个元素obj->k = k; //队列的长度为kreturn obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//队空,就是队头与队尾相同时return obj->front == obj->tail;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->tail+1)%(obj->k+1) == obj->front;
}//插入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//插入元素前先进行判断是否满if(myCircularQueueIsFull(obj)){return false;}//插入元素使用尾插obj->a[obj->tail] = value;obj->tail++;//避免tail的下标越界obj->tail%=(obj->k+1);return true;
}//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//删除元素队列不能为空if(myCircularQueueIsEmpty(obj)){return false;}//出队,头删obj->front++;obj->front%=(obj->k+1);return true;
}//获取队首元素
int myCircularQueueFront(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}return obj->a[obj->front];
}//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {//队列不能为空if(myCircularQueueIsEmpty(obj)){return -1; //队空返回-1}//注意当tail = 0的情况return obj->a[(obj->tail - 1+ obj->k+1)%(obj->k+1)];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}/*** Your MyCircularQueue struct will be instantiated and called as such:* MyCircularQueue* obj = myCircularQueueCreate(k);* bool param_1 = myCircularQueueEnQueue(obj, value);* bool param_2 = myCircularQueueDeQueue(obj);* int param_3 = myCircularQueueFront(obj);* int param_4 = myCircularQueueRear(obj);* bool param_5 = myCircularQueueIsEmpty(obj);* bool param_6 = myCircularQueueIsFull(obj);* myCircularQueueFree(obj);
*/
相关文章:
Leetcode:622. 设计循环队列 题解【具详细】
目录 一、题目: 二、思路详解: 1.循环队列的存储定义 2.循环队列的创建 3.循环队列的判空与判断情况 (1) 循环队列的判空: (2) 循环队列的判满 4.循环队列元素的插入 5.循环队列元素的删除 6.获取队头元素 7.获取队尾元素 8.循环队列释放 三…...
ArkTS基础知识 【习题】
判断题 1.循环渲染ForEach可以从数据源中迭代获取数据,并为每个数组项创建相应的组件。 正确(True) 2. Link变量不能在组件内部进行初始化。 正确(True) 单选题 1.用哪一种装饰器修饰的struct表示该结构体具有组件化能力?(A) A. Component B. Entry C…...
是否有无限提取的代理IP?作为技术你需要知道这些
最近有互联网行业的技术小伙伴问到,有没有可以无限提取的代理IP?就是比如我一秒钟提取几万、几十万次,或者很多台机器同时调用API提取链接,这样可以吗?看到这个问题,不禁沉思起来,其实理论上是存…...
【算法萌新闯力扣】:卡牌分组
力扣热题:卡牌分组 一、开篇 今天是备战蓝桥杯的第22天。这道题触及到我好几个知识盲区,以前欠下的债这道题一并补齐,哈希表的遍历、最大公约数与最小公倍数,如果你还没掌握,这道题练起来! 二、题目链接:…...
深入解析:如何开发抖音票务小程序
当下,开发抖音票务小程序成为了吸引年轻用户群体的一种创新方式。本文将深入解析如何开发抖音票务小程序,探讨关键步骤和技术要点。 1.确定需求和功能 考虑到抖音的用户特点,可以加入与短视频相关的票务功能,如在线购票、观影记录…...
vue中 mixin用法
在Vue.js中,mixin是一种可以在多个组件之间共享Vue组件选项的灵活方式。mixin对象可以包含任何组件选项。当组件使用mixin时,所有mixin对象的选项将被“混合”到该组件的选项中。 使用mixin的一个主要优点是可以在多个组件之间重用和共享代码。这可以帮…...
Java入门基础:浅显易懂 while
文章目录 前言一、布尔表达式二、while三、语法四、示例 前言 在开发过程中不管是 while 语句还是其他语句都会经常用到布尔表达式,所以在学习 while 之前需要先明白什么是布尔表达式? 一、布尔表达式 布尔表达式只有2种结果:true / false 看…...
DNS/ICMP协议、NAT技术
目录 DNS协议DNS背景域名简介 ICMP协议ICMP功能ping命令traceroute命令 NAT技术NAT技术背景NAT IP转换过程NAPTNAT技术的缺陷NAT和代理服务器 网络协议总结应用层传输层网络层数据链路层 DNS协议 DNS(Domain Name System,域名系统)协议&…...
React整理总结(七、Hooks)
1.Class组件的优缺点 优点 class组件可以定义自己的state,用来保存组件自己内部的状态;函数式组件不可以,因为函数每次调用都会产生新的临时变量;class组件有自己的生命周期,我们可以在对应的生命周期中完成自己的逻…...
软件测试之银行测试详解
一、金融类软件测试 举个栗子,银行里的软件测试工程师。横向跟互联网公司里的测试来说,薪资相对稳定,加班的话想对来说没那么多(有些银行加班也挺严重的),但业务稳定。实在是测试类岗位中的香饽饽…...
C#中的警告CS0120、CS0176、CS0183、CS0618、CS8600、CS8602、CS8604、CS8625及处理
目录 一、CS0120 二、CS0176 1.解决前 2.解决后 3.解决办法 三、CS0183 四、CS0618 五、CS8600 六、CS8602 七、CS8622 1. 解决前: 2. 解决后: 3.解决方法: 八、CS8604和CS8625 一、CS0120 严重性 代码 说明 项目 文件 行…...
CSS:浏览器设置placeholder样式 / 微信小程序设置placeholder样式
一、web 设置placeholder 设置浏览器的placeholder样式 ::-webkit-input-placeholder { /* WebKit browsers */color: #999; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */color: #999; } ::-moz-placeholder { /* Mozilla Firefox 19 */color: #999; } :-ms-input-p…...
升级python后sudo apt-get update报错
sudo apt-get update 报错: sh: /usr/lib/cnf-update-db: /usr/bin/python3.7.5: bad interpreter: No such file or directory Reading package lists... Done E: Problem executing scripts APT::Update::Post-Invoke-Success if /usr/bin/test -w /var/lib/c…...
应用可观测性OpenTelemetry简介
应用可观测性OpenTelemetry简介 OpenTelmetry遥测方案可观测性三支柱日志 Logs指标跟踪 什么是OpenTelemetryOpenTelemetry架构和组件OpenTelemetry与OpenCensus、OpenTracing是什么关系 OpenTelmetry遥测方案 可观测性三支柱 日志 Logs 日志是特定事件在特定时间点发生的文本…...
install pnpm : 无法加载文件的解决办法
问题描述 我在使用pnpm的时候报错 PS D:\emss\pure-admin-backend> pnpm install pnpm : 无法加载文件 C:\Users\RD-16\AppData\Roaming\npm\pnpm.ps1。未对文件 C:\Users\RD-16\AppData\Roaming\npm\pnpm.ps1 进行数字签名。无法在当前系统上运 行该脚本。有关运行脚本和设…...
【Python百宝箱】Python数据探险:Excel与数据科学的完美结合
前言 在当今信息爆炸的时代,数据处理和分析已经成为各行各业不可或缺的一部分。在众多数据处理工具中,Python以其简洁而强大的语法成为数据科学家和分析师的首选之一。本文将深入探讨与电子表格处理相关的Python库,介绍它们的功能、应用场景…...
外贸分享|如何从外贸小白成长为大咖?这10件事值得你坚持做
外贸成功不是一朝一夕的事,而是需要有充分的准备和持续的努力。作为一位有着丰富经验的外贸人员,我总结了成功的秘诀,分享了一个优秀的外贸人应该做好的10项工作。 1 找不到客户怎么办? 有很多各种各样的原因值得思考:…...
深度学习之六(自编码器--Autoencoder)
概念 自编码器(Autoencoder)是一种神经网络架构,用于无监督学习和数据的降维表示。它由两部分组成:编码器(Encoder)和解码器(Decoder)。 结构: 编码器(Encoder): 接收输入数据并将其压缩为潜在表示(latent representation),通常比输入数据的维度要低。编码器的…...
Docker Swarm总结+基础、集群搭建维护、安全以及集群容灾(1/3)
博主介绍:Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 🍅文末获取源码下载地址🍅 👇🏻 精彩专栏推荐订阅👇🏻…...
Vim 一下日志文件,Java 进程没了?
一次端口告警,发现 java 进程被异常杀掉,而根因竟然是因为在问题机器上 vim 查看了 nginx 日志。下面我将从时间维度详细回顾这次排查,希望读者在遇到相似问题时有些许启发。 时间线 15:19 收到端口异常 odin 告警。 状态:P1故障 名称:应用端…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
