当前位置: 首页 > news >正文

L33.【LeetCode笔记】循环队列(数组解法)

目录

1.题目

2.分析

方法1:链表

尝试使用单向循环链表模拟

插入节点

解决方法1:开辟(k+1)个节点

解决方法2:使用变量size记录队列元素个数

获取队尾元素

其他函数的实现说明

方法2:数组

重要点:指针越界的解决方法

方法1:单独判断

方法2:取模

3.数组代码的逐步实现

方法1:越界时单独判断

提交结果

方法2:每次都取模

提交结果


1.题目

https://leetcode.cn/problems/design-circular-queue/

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。

示例:

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

提示:

  • 所有的值都在 0 至 1000 的范围内;
  • 操作数将在 1 至 1000 的范围内;
  • 请不要使用内置的队列库。

2.分析

方法1:链表

看到本题,很容易想到用链表解

尝试使用单向循环链表模拟

例如k==3,很容易想到开辟三个空节点

要访问循环队列的头和尾,需要两个指针front(头指针)和rear(尾指针),初始状态下,链表为空时,front和rear都指向同一个节点

现检测链表的功能是否能正常执行

插入节点

每插入一个元素,按队列"先进先出"原则,应该rear++,如下图:

当队列满时,如下图:

发现问题:队列为空或满时,front和rear都指向同一个节点,无法区分

解决方法1:开辟(k+1)个节点

增加一个节点后,当队列满时,rear->next==front;当队列为空时,rear==front

解决方法2:使用变量size记录队列元素个数

当队列为空时,size==0;当队列满时,size==k.以此来区分两种情况

获取队尾元素

无论开辟(k+1)个节点还是使用变量size记录队列元素个数,rear都指向尾节点的下一个节点,需要找尾(时间复杂度为,较消耗时间),或者另外使用一个rear_prev变量来记录rear指向节点的前一个节点,或者使用双向链表

其他函数的实现说明

从队首获取元素:返回front指向的节点的值即可

删除一个元素:front++

方法2:数组

讲讲和链表的不同点:

重要点:指针越界的解决方法

1.无论开辟(k+1)个节点还是使用变量size记录队列元素个数,front和rear都有越界的可能性

以开辟(k+1)个节点举例:

例如下图,再插入一个元素,如果rear++,则会越界

例如下图,再删除一个元素,如果front++,则会越界

 2.获取队尾元素时,可能出现rear越界访问的情况

当队列不为空时,直接访问return obj->arr[obj->rear-1];可能访问到obj->arr[-1]的位置,可以单独判断或者对rear取模

方法1:单独判断

如果rear+1越界,则rear=0;如果front+1越界,则front=0;

方法2:取模

队列未满时,插入元素:当rear==k时,再插入元素时rear++,之后处理越界的rear,使其等于0,则,rear==(rear+1)%(k+1)

队列不为空时,删除元素:当front==k时,再插入元素时front++,之后处理越界的front,使其等于0,则,front==(front+1)%(k+1)

队列不为空时,访问队尾元素:例如rear==0,要访问到rear==k的位置,即arr[(rear-1+k+1)%(k+1)==arr[(rear+k)%(k+1)

判断队列是否已满,如果满了,例如rear==k,要使rear的下一个为front==0,即判断(rear+1)%(k+1)==front

3.数组代码的逐步实现

读题可知:如果用数组来模拟循环队列,那么结构体成员变量应该有4个

1.指向数组的指针a,类型为int*

2.队首和队尾各需要一个变量来访问:front和rear,类型都为int,充当数组a的下标

3.队列的长度k,类型为int

显然应该用malloc在堆区上开辟空间,接收的指针为结构体指针,否则函数返回后,栈区空间会被销毁

之后初始化结构体的成员变量

方法1:越界时单独判断

typedef struct 
{int* arr;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) 
{MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->arr=(int*)malloc(sizeof(int)*(k+1));obj->front=obj->rear=0;obj->k=k;return obj;
}bool myCircularQueueIsFull(MyCircularQueue* obj);//先声明
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//先声明
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{if (myCircularQueueIsFull(obj))return false;if (obj->rear!=obj->k)obj->arr[obj->rear++]=value;elseobj->rear=0;obj->arr[obj->k]=value;return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj))return false;if (obj->front!=obj->k)obj->front++;elseobj->front=0;return true;}int myCircularQueueFront(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj))return -1;return obj->arr[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj))return -1;if (obj->rear)//rear!=0return obj->arr[obj->rear-1];//rear==0return obj->arr[obj->k];
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{return obj->front==obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) 
{int rear_copy=obj->rear;if (rear_copy+1==obj->front)return true;else if (rear_copy==obj->k && obj->front==0)return true;elsereturn false;
}void myCircularQueueFree(MyCircularQueue* obj) 
{free(obj->arr);free(obj);
}

代码还可以精简些,例如

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{return (obj->rear+1==obj->front) || (obj->rear==obj->k && obj->front==0);
}

提交结果

方法2:每次都取模

★注意:rear++或者front++后一定要取模!

typedef struct 
{int* arr;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) 
{MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->arr=(int*)malloc(sizeof(int)*(k+1));obj->front=obj->rear=0;obj->k=k;return obj;
}bool myCircularQueueIsFull(MyCircularQueue* obj);//先声明
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//先声明
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{if (myCircularQueueIsFull(obj))return false;obj->arr[obj->rear++]=value;obj->rear%=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;return obj->arr[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) 
{if (myCircularQueueIsEmpty(obj))return -1;return obj->arr[(obj->rear-1+obj->k+1)%(obj->k+1)];
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{return obj->front==obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) 
{return (obj->rear+1)%(obj->k+1)==obj->front;
}void myCircularQueueFree(MyCircularQueue* obj) 
{free(obj->arr);free(obj);
}

提交结果

注:有关本题的链表解法参见下一篇

相关文章:

L33.【LeetCode笔记】循环队列(数组解法)

目录 1.题目 2.分析 方法1:链表 尝试使用单向循环链表模拟 插入节点 解决方法1:开辟(k1)个节点 解决方法2:使用变量size记录队列元素个数 获取队尾元素 其他函数的实现说明 方法2:数组 重要点:指针越界的解决方法 方法1:单独判断 方法2:取模 3.数组代码的逐步实现…...

css实现元素垂直居中显示的7种方式

文章目录 * [【一】知道居中元素的宽高](https://blog.csdn.net/weixin_41305441/article/details/89886846#_1) [absolute 负margin](https://blog.csdn.net/weixin_41305441/article/details/89886846#absolute__margin_2) [absolute margin auto](https://blog.csdn.net…...

【Python】Django 中的算法应用与实现

Django 中的算法应用与实现 在 Django 开发中,算法的应用可以极大地扩展 Web 应用的功能和性能。从简单的数据处理到复杂的机器学习模型,Django 都可以作为一个强大的后端框架来支持这些算法的实现。本文将介绍几种常见的算法及其在 Django 中的使用方法…...

Docker 运行 GPUStack 的详细教程

GPUStack GPUStack 是一个用于运行 AI 模型的开源 GPU 集群管理器。它具有广泛的硬件兼容性,支持多种品牌的 GPU,并能在 Apple MacBook、Windows PC 和 Linux 服务器上运行。GPUStack 支持各种 AI 模型,包括大型语言模型(LLMs&am…...

Kubernetes中的 iptables 规则介绍

#作者:邓伟 文章目录 一、Kubernetes 网络模型概述二、iptables 基础知识三、Kubernetes 中的 iptables 应用四、查看和调试 iptables 规则五、总结 在 Kubernetes 集群中,iptables 是一个核心组件, 用于实现服务发现和网络策略。iptables 通…...

解决VScode 连接不上问题

问题 :VScode 连接不上 解决方案: 1、手动杀死VS Code服务器进程,然后重新尝试登录 打开xshell ,远程连接服务器 ,查看vscode的进程 ,然后全部杀掉 [cxqiZwz9fjj2ssnshikw14avaZ ~]$ ps ajx | grep vsc…...

AI 驱动的软件测试革命:从自动化到智能化的进阶之路

🚀引言:软件测试的智能化转型浪潮 在数字化转型加速的今天,软件产品的迭代速度与复杂度呈指数级增长。传统软件测试依赖人工编写用例、执行测试的模式,已难以应对快速交付与高质量要求的双重挑战。人工智能技术的突破为测试领域注…...

【Java代码审计 | 第六篇】XSS防范

文章目录 XSS防范使用HTML转义使用Content Security Policy (CSP)输入验证使用安全的库和框架避免直接使用用户输入构建JavaScript代码 XSS防范 使用HTML转义 在输出用户输入时,对特殊字符进行转义,防止它们被解释为HTML或JavaScript代码。 例如&…...

Android WebSocket工具类:重连、心跳、消息队列一站式解决方案

依赖库 使用 OkHttp 的WebSocket支持。 在 build.gradle 中添加依赖: implementation com.squareup.okhttp3:okhttp:4.9.3WebSocket工具类实现 import okhttp3.*; import android.os.Handler; import android.os.Looper; import android.util.Log;import java.ut…...

认识vue2脚手架

1.认识脚手架结构 使用VSCode将vue项目打开: package.json:包的说明书(包的名字,包的版本,依赖哪些库)。该文件里有webpack的短命令: serve(启动内置服务器) build命令…...

【STM32】STM32系列产品以及新手入门的STM32F103

📢 STM32F103xC/D/E 系列是一款高性能、低功耗的 32 位 MCU,适用于工业、汽车、消费电子等领域;基于 ARM Cortex-M3,主频最高 72MHz,支持 512KB Flash、64KB SRAM,适合复杂嵌入式应用,提供丰富的…...

<建模软件安装教程1>Blender4.2系列

Blender4.2安装教程 0注意:Windows环境下安装 第一步,百度网盘提取安装包。百度网盘链接:通过网盘分享的文件:blender.zip 链接: https://pan.baidu.com/s/1OG0jMMtN0qWDSQ6z_rE-9w 提取码: 0309 --来自百度网盘超级会员v3的分…...

CentOS Docker 安装指南

CentOS Docker 安装指南 引言 Docker 是一个开源的应用容器引擎,它允许开发者打包他们的应用以及应用的依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。Docker 容器是完全使用沙箱机制,相互之…...

分布式ID生成方案:数据库号段、Redis与第三方开源实现

分布式ID生成方案:数据库号段、Redis与第三方开源实现 引言 在分布式系统中,全局唯一ID生成是核心基础能力之一。本文针对三种主流分布式ID生成方案(数据库号段模式、Redis方案、第三方开源框架)进行解析,从实现原理…...

tcc编译器教程2 编译lua解释器

本文主要介绍了使用tcc编译器编译lua解释器源码。 1 介绍 lua是一门编程语言,开源且源码很容易编译,我平时用来测试C语言编程环境时经常使用。一般能编译成功就说明编程环境设置正常。下面用之前设置好的tcc编程环境进行测试。 2 获取源码 我一般有保留多个版本的lua源码进…...

利用 requestrepo 工具验证 XML外部实体注入漏洞

1. 前言 在数字化浪潮席卷的当下,网络安全的重要性愈发凸显。应用程序在便捷生活与工作的同时,也可能暗藏安全风险。XXE(XML外部实体)漏洞作为其中的典型代表,攻击者一旦利用它,便能窃取敏感信息、掌控服务…...

在 Maven 中使用 <scope> 元素:全面指南

目录 前言 在 Maven 中, 元素用于定义依赖项的作用范围,即依赖项在项目生命周期中的使用方式。正确使用 可以帮助我们优化项目的构建过程,减少不必要的依赖冲突,并提高构建效率。本文将详细介绍 的使用步骤、常见作用范围、代码…...

uni_app实现下拉刷新

1. 在页面配置中启用下拉刷新 首先,你需要在页面的 pages.json 文件中启用下拉刷新功能。 {"pages": [{"path": "pages/index/index","style": {"navigationBarTitleText": "首页","enablePull…...

PCIe协议之RCB、MPS、MRRS详解

✨前言: PCIe总线的存储器写请求、存储器读完成等TLP中含有数据负载,即Data Payload。Data Payload的长度和MPS(Max Payload Size)、MRRS(Max Read Request Size)和RCB(Read Completion Bounda…...

达梦数据库在Linux,信创云 安装,备份,还原

(一)系统环境检查 1操作系统:确认使用的是国产麒麟操作系统,检查系统版本是否兼容达梦数据库 V8。可以通过以下命令查看系统版本: cat /etc/os-release 2硬件资源:确保服务器具备足够的硬件资源&#xff0…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

如何为服务器生成TLS证书

TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...