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

OJ:循环队列

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

思路 

思路:首先循环队列的意思是:空间固定,就是提前开辟好,满了就不能插入了,但是删除数据后仍有空间,删除循环队列里面的数据后,保留它的空间,就能再插入数据,即可以重复利用之前删除的空间。

这一题的循环让我们想到一个约瑟夫环的问题,所以这题我们不加哨兵位,因为加哨兵位转的时候就可能不太好操作。

猜想:front和rear指向空(指向同一个位置),问题:得单独判断插入第一个数据的时候如何,因为你0个数据和1个数据的时候是分不清的。

对front和rear都指向空的疑问:队列有头有尾,front为头,rear为尾,两者为空指向同一节点,意味着你插入一个数据时,尾要往后走一下。这样rear有点像栈中的意思了,top意味它不是指向栈顶元素,而是指向栈顶元素的下一个。

对rear指向尾的下一个的疑问:,如果front、rear相等为空,那么满时front也等于rear,所以无法判断空和满。

因此到这里:我们最好选择rear指向尾的下一个。

改进:当然可以用size来记录链表的长度,从而区分满不满,代入接口,发现找尾不好找,所以我们能不能加一个rear的prev前驱指针从而来找尾,但是好像有点不好控制,如果这样的话,还不如直接双向链表,因此链表看起来虽然简单,但越解决越复杂。这里我们想到对于数组能够随意访问下标,我们可以尝试一下数组。

我们先来总结一下链表的点:

1.rear为尾的下一个,得改成双向才好控制。

2.rear指向最后一个,初始化和为空的时候得做特殊处理。

因此综上所述,用数组可能选择更好。

分析:rear指向尾不好,指向尾的话,初始化的话,你先初始化为0时,你是初始化的0还是插入的0是无法判断的,而且在删除的时候也要单独删除最后一个。所以我们使得rear指向尾的下一个。

其次,虽然使得rear指向尾的下一个,但是我们之前上述的疑问中所说的,空和满无法判断,这里我们称为假溢出问题。

以k=4举例,我们要多开一个空间,对多开空间而言,front等于rear即为空,因为是数组吗,我们可以直接用下标来进行访问,循环的话就用一下下标回绕的思路就好了。

rear加1回绕到front就为满。当然回绕吗,就是取模,%(k+1),对于删除来说,删除一次就往后走一次,当front等于rear时就为空。回绕的问题就解决了。

总结数组的好处:数组好找,这里rear是指向尾的下一个的,运用数组可以找到尾。

ok,我们要的条件是:front指向头、rear指向尾的下一个、多开一个空间。

当然这题已经给定空间,数组开辟好了空间之后,初始化就可以控制了,一个指向头,一个指向尾的下一个,所以相当于左闭右开。左闭右开才可以在最开始都为空,如果是左闭右闭初始化就有问题,我们在链表初始化的时候已经说过。

创建结构体 

 我们先看这个代码中给的这个结构体

typedef struct {} MyCircularQueue;

 前面我们分析过,为了实现这个循环队列我们要一个front代表头,rear指向尾的下一个,当然有个整型指针用来指向我们的数据,这里我们传递个我们这个数字的有效节点。

typedef struct {int* a;int front;int rear;int k;
} MyCircularQueue;

 构建循环队列

接下来开始创建,对应创建的话,先创建整个结构体,在对里面的指针进行malloc,记住这里我们多扩一个。当然也需要初始化一下构建的结构体里面的数据。

MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));int* b=(int*)malloc(sizeof(int)*(k+1));obj->a=b;obj->front=0;obj->rear=0;obj->k=k;return obj;
}

判空 

之后我们先写一下判断是否为空,front==rear时就为空

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->rear;
}

判满 

 接下来是判断是否为满,这个时候结对考虑轮转数组的问题了,当然%(k+1)对于没有到达下标为4的没有影响(以k=4时为例)。

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

释放 

然后我们先写一下比较好写的释放吧,就是释放obj的a,再释放obj,因为obj是指针,这里传递的也是指针,因此这里可以不用把obj置为空。

void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}

 接下来还有四个接口没写,分别是插入数据,删除数据,取队头元素,取队尾元素。

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {}bool myCircularQueueDeQueue(MyCircularQueue* obj) {}int myCircularQueueFront(MyCircularQueue* obj) {}int myCircularQueueRear(MyCircularQueue* obj) {}

 取对头元素和取队尾元素

我们先来写取对头元素和取队尾元素两个接口吧,首先这两个我们都得先判断他们是否为空,如果为空,就直接跳出循环,取对头元素比较好取,直接用front的下标就能取到,但是对于取队尾元素呢,好像不能直接写,可能得考虑取模的情况,因为可能会遇到下面这种情况。

int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}

 插入元素和删除元素

 ok,到了这里我们还剩下插入元素和删除元素,首先对应插入元素来说,我们得先判断是否满了,如果元素满了,那么由于空间是给定的,所以无法再继续插入了。如果没有满,就先考虑下图这种情况

这时rear再最后一个,这个时候要插入元素,应该回转rear。 所以应该利用取模。而对于删除元素来说,先要判断是否为空,如果为空,那么就无法删除,就直接退出,然后这里的回转运用到了我们找队尾元素的思路。

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->rear]=value;obj->rear=(obj->rear+1)%(obj->k+1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return false;}obj->front=(obj->front+1)%(obj->k+1);return true;
}

最终代码 

typedef struct {int* a;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));int* b=(int*)malloc(sizeof(int)*(k+1));obj->a=b;obj->front=0;obj->rear=0;obj->k=k;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear+1)%(obj->k+1)==obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->rear]=value;obj->rear=(obj->rear+1)%(obj->k+1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return false;}obj->front=(obj->front+1)%(obj->k+1);return true;
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}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);
*/

相关文章:

OJ:循环队列

622. 设计循环队列 - 力扣(LeetCode) 思路 思路:首先循环队列的意思是:空间固定,就是提前开辟好,满了就不能插入了,但是删除数据后仍有空间,删除循环队列里面的数据后,保…...

专业140+总430+电子科技大学858信号与系统考研经验成电电子信息与通信工程,电科大,真题,大纲,参考书。

今年考研成绩出来,初试专业课858信号与系统140,总分430,其余各门分数都比较平稳,总分好于自己估分,应群里很多同学要求,我总结一下自己的复习经验。首先我是一个大冤种,专业课资料学长给了一套&…...

C++:STL - set map

C:STL - set & map 关联式容器pairset模板参数typedef的类型构造函数迭代器常规接口特殊接口 multisetmap模板参数typedef的类型常规接口特殊接口 multimap 关联式容器 关联式容器是C标准库提供的一种数据结构,用于存储操作键值对(key-v…...

一招鲜吃遍天之Haproxy集群

四层: LVS:Linux Virtual Server Nginx: HAProxy:High Availability Proxy 七层: HAProxy Nginx 硬件: F5 F5 | 多云安全和应用交付 Netscaler NetScaler: Application Delivery at Scale Array 北京华耀科技…...

数据库的筛选条件

【一】筛选过滤条件 【1】完整的查询语句 -- 查询当前表中的全部数据select * from 表名 where 筛选条件;​-- 查询当前表中的指定字段的数据select 字段名,字段名 from 表名 where 筛选条件;# 执行顺序from where select ​select 你选择的列1, 你选择的列2, ... from 查询的…...

MySQL学习笔记(一)数据库事务隔离级别与多版本并发控制(MVCC)

一、数据库事务隔离级别 数据库事务的隔离级别有4种,由低到高分别为Read uncommitted (读未提交)、Read committed(读提交) 、Repeatable read(可重复读) 、Serializable (串行化&a…...

如何在Linux上为PyCharm创建和配置Desktop Entry

在Linux操作系统中,.desktop 文件是一种桌面条目文件,用于在图形用户界面中添加程序快捷方式。本文将指导您如何为PyCharm IDE创建和配置一个 .desktop 文件,从而能够通过应用程序菜单或桌面图标快速启动PyCharm。 步骤 1: 确定PyCharm安装路…...

Igraph入门指南 4

二、图的创建 图分有向图和无向图,所以图的创建有各自的实现方式。 1、手工创建图: 1-1 通过文本创建:graph_from_literal 通过每项提供两个顶点名(或ID号)作为一条边的格式,手动创建图,顶点…...

外包干了30天,技术明显退步。。

🍅 视频学习:文末有免费的配套视频可观看 🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 这次来聊一个大家可能也比较关心的问题,那就是就业城市选择的问题。而谈到这个问题&a…...

数据库 — 增删查改

一、操作数据库、表 显示 show databases;创建 create database xxx;使用 use xxx; 删除 drop database xxx;查看表; show tables; 查看表结构 desc 表名; 创建 create table 表名(字段1 类型1,字段2 类型2,.... ); 删除 drop table 表名; 二…...

eclipse搭建java web项目

准备条件 eclipsejdk1.8 (配置jdk环境)apache-tomcat-8.5.97(记住安装位置) 一 点击完成 开始创建javaweb项目 import java.io.IOException; import java.io.PrintWriter;import javax.servlet.ServletException; import javax.s…...

gitlab-ci_cd语法CICD

工作原理 1、将代码托管在git 2、在项目根目录创建ci文件.gitlan-ci.yml 在文件中指定构建,测试和部署脚本 3、gitlab将检测到他并使用名为git Runner的工具运行脚本 4、脚本被分组为作业,他们共同组成了一个管道gitlab-ci的脚本执行,需要自…...

python 蓝桥杯之动态规划入门

文章目录 DFS滑行(DFS 记忆搜索) 思路: 要思考回溯怎么写(入参与返回值、递归到哪里,递归的边界和入口) DFS 滑行(DFS 记忆搜索) 代码分析: 学会将输入的数据用二维列表…...

[LeetCode][102]二叉树的层序遍历——遍历结果中每一层明显区分

题目 102. 二叉树的层序遍历 给定二叉树的根节点 root,返回节点值的层序遍历结果。即逐层地,从左到右访问所有节点。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2: 输入…...

GIS之深度学习10:运行Faster RCNN算法

(未完成,待补充) 获取Faster RCNN源码 (开源的很多,论文里也有,在这里不多赘述) 替换自己的数据集(图片标签文件) (需要使用labeling生成标签文件&#xf…...

appium2的一些配置

appium-desktop不再维护之后,需要使用appium2。 1、安装appium2 命令行输入npm i -g appium。安装之后输入appium或者appium-server即可启动appium 2、安装安卓/ios的驱动 安卓:appium driver install uiautomator2 iOS:appium driver i…...

基于springboot+vue实现高校学生党员发展管理系统项目【项目源码+论文说明】

基于springboot实现高校学生党员发展管理系统演示 摘要 随着高校学生规模的不断扩大,高校内的党员统计及发展管理工作面临较大的压力,高校信息化建设的不断优化发展也进一步促进了系统平台的应用,借助系统平台可以实现更加高效便捷的党员信息…...

Java代码审计安全篇-常见Java SQL注入

前言: 堕落了三个月,现在因为被找实习而困扰,着实自己能力不足,从今天开始 每天沉淀一点点 ,准备秋招 加油 注意: 本文章参考qax的网络安全java代码审计,记录自己的学习过程,还希望…...

C#实现快速排序算法

C#实现快速排序算法 以下是C#中的快速排序算法实现示例: using System;class QuickSort {// 快速排序入口函数public static void Sort(int[] array){QuickSortRecursive(array, 0, array.Length - 1);}// 递归函数实现快速排序private static void QuickSortRecu…...

upload-labs通关记录

文章目录 前言 1.pass-012.pass-023.pass-034.pass-045.pass-056.pass-067.pass-078.pass-089.pass-0910.pass-1011.pass-1112.pass-1213.pass-1314.pass-1415.pass-1516.pass-1617.pass-1718.pass-1819.pass-19 前言 本篇文章记录upload-labs中,所有的通过技巧和各…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...