好题分享(2023.11.19——2023.11.25)

news2025/1/11 3:02:57

目录

​编辑

前情回顾:

前言:

认识循环队列:

实现循环队列的思路:

题目:《设计循环队列》 

1.判满和判空:

2.添加数据和删除

3.计算循环队列的数据个数

 4.返回对队尾元素

总结:


前情回顾:

我们在上一篇好题分析中,分析了以下几题:

《有效括号》《用队列实现栈》《用栈实现队列》

上一篇的好题分析的blog:好题分享(2023.11.12——2023.11.18)-CSDN博客

前言:

 在本周的好题分享当中,我们需要了解一下关于循环队列的基础知识,以及代码OJ题。

因此本周的好题分享,有且仅有一道Leecode的OJ题——《设置循环队列》

认识循环队列:

循环队列是一种特殊类型的队列,它通过使用固定大小的数组(或其他数据结构)来实现队列的基本操作。循环队列克服了普通队列在出队列后无法再次利用队列空间的问题。
以下是循环队列的一些特点和基本操作:
特点:

1.使用数组: 循环队列使用数组来存储元素。
2.固定大小: 循环队列有一个固定的大小,这意味着它的空间是有限的。
3.循环利用空间: 当队列的尾部到达数组的末尾时,下一个元素将被插入到数组的开头,实现了循环利用队列的空间。

基本操作:

4.初始化: 初始化循环队列,需要指定数组的大小,并设置前端(Front)和后端(Rear)的初始位置。
5.入队列(enqueue): 将元素添加到队列的尾部。在普通队列中,尾部指针会一直向后移动;而在循环队列中,如果尾部指针已经到达数组的末尾,下一个元素将被插入到数组的开头。
6.出队列(dequeue): 从队列的前端移除元素。在普通队列中,前端指针会一直向后移动;而在循环队列中,如果前端指针已经到达数组的末尾,下一个元素将在数组的开头。
7.判空(isEmpty): 检查循环队列是否为空。
8.判满(isFull): 检查循环队列是否已满。

示意图:

Front                  Rear
   |                     |
+---+---+---+---+---+
| 3 | 9 | 7 |   |   |
+---+---+---+---+---+

在这个示意图中,Front 指向元素3,Rear 指向元素7。如果入队列一个新元素,它将被插入到Rear的后一个位置,实现了循环。
 

 

实现循环队列的思路:

对于我们该如何实现循环队列是一个需要我们深思的问题,我们可以使用顺序表来完成我们循环队列的实现,具体操作如下:

1.开辟k个空间的顺序表,但我们故意多开辟一个空间,其中这个空间里不含有任何数据!

2.此时我们就可以利用这个多余的空间进行一系列的操作,最重要的判空和判满都有了很好地解决措施!

 

 

题目:《设计循环队列》 

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

 




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

MyCircularQueue* myCircularQueueCreate(int k) {
	MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	obj->a = (int*)malloc(sizeof(int)* (k + 1));
	obj->front = obj->back = 0;
	obj->k = k;
	return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {

	if ((obj->back + 1) % (obj->k + 1) == obj->front)
	{
		return false;
	}

	obj->a[obj->back] = value;
	obj->back++;
	obj->back = obj->back % (obj->k + 1);
	return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (obj->front == obj->back)
	{
		return false;
	}
	obj->front++;
	obj->front = obj->front % (obj->k + 1);
	return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
	if (obj->front == obj->back)
	{
		return -1;
	}
	return obj->a[obj->front];
}

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

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
	if (obj->front == obj->back)
	{
		return true;
	}
	return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
	if ((obj->back + 1) % (obj->k + 1) == obj->front)
	{
		return true;
	}
	return false;
}

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);
*/

1.判满和判空:

对于任何循环队列,我们应当清楚队列为空是什么样子的,队列满了是什么样子的?

队列为空:back == front;

队列满:(back + 1)%(k+1) == front;

这里的“空数据”其实就是队列的头位置,即front指向的地方。

循环队列我们可以把它想象成一个圆圈来看,但是其逻辑存储应当以顺序表的视野来看。

这里的取模操作,意思和之前我们讲的循环链表类似。

即back到达K+1的位置时,相当于转了一圈,因此我们取模k+1则会得到0.

0就为整个队列也是圈的起点。

 

 

2.添加数据和删除

 

 添加数据好理解,就是back遍历,遍历到的地方就赋值操作,同时back++。

当back如图时,此时就是满的。将不再进行添加数据。

我们先讲到这里,待会还会进行补充。

如果现在我们想要删除数据且删除的是第一个数据。

我们可以直接front++即可。如图:

原本的数据可以不释放,也可以不置空。

因为此时的front指向的是下标为1的地方,所以(back + 1) % (k+1) != front

所以我们还是可以进行增加数据的操作。

此时此刻,我们就可以在我们新开辟出来的那一块空间增加数据。

同时原来front指向的那块空间,就变成了之前的临时空间,如图:

我们再次进行判满操作:(back+1) == 7   (k+1) == 6   7%6 == 1

此时front == 1,所以当前是满的,这个代码实现也没问题。

但是!

如果我继续删除,front就会++到下标为2的地方,如图:

 

那我还想要增加数据,那back此时已经越界了,增加数据也只能在下标为0的地方增加,那我的back该怎么回到下标为0的地方呢?

很简单

back = back % (k+1);

只要back一到达k+1的位置时,取模操作就会变成0,这样就会直接返回到下标为0的地方。

而只要小于k+1也不会有事,因为%一个比自己大的数就是自己。

所以就有如图:

 

back就会回到这里。

 同理front也会最终++到越界,所以我们也需要将

front = front % k+1.

如此增加数据和删除数据的思路就此全部实现。

3.计算循环队列的数据个数

 我们通过之前的学习,对于数组的下标和数组的元素个数肯定有一定的理解,我们不难发现

下标数 == 该下标之前的元素个数

所以求数据个数可以选择 back - front

但是如果是这种情况:

此时是满的,本来是5个数据,这么算下来缺是-1个数,很明显这是不对的。

因为我们没有考虑到该队列是一个循环队列!

如果出现了以上的情况,back在front和后面,我们可以得出结论,back至少走了一圈

所以我们可以

(back - front + (k+1)) % (k+1)

 4.返回对队尾元素

 这里我们同样也需要特别注意,因为我们在添加完数据后,back会++,也可能会返回到下标为0的位置。

因此我们可不能直接return a[back--];

我们应当 (K + back) % k+ 1;

总结:

关于实现一个循环队列我们就讲到这里,本题难度不大,我们只要动手画一画图就可以写出这些代码,思路才是最重要的!

下一篇blog我们会开启《树》的内容并且介绍介绍堆。

记住“坐而言不如起而行”

Action speak louder than words.

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

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

相关文章

内部类, Comparable接口, Comparator接口, Cloneable接口 ---java

目录 一. 内部类 1.1 静态内部类 1.2 实例内部类 1.3匿名内部类 二. 接口的使用实例 2.1 Comparable接口 2.2 Comparator接口 ---比较器 2.3 Cloneable接口 深拷贝浅拷贝 一. 内部类 当一个事物的内部,还有一个部分需要一个完整的结构进行描述&#xff0…

从零开始学Go web——第一天

文章目录 从零开始学Go web——第一天一、Go与web应用简介1.1 Go的可扩展性1.2 Go的模块化1.3 Go的可维护1.4 Go的高性能 二、web应用2.1 工作原理2.2 各个组成部分2.2.1 处理器2.2.2 模板引擎 三、HTTP简介四、HTTP请求4.1 请求的文本数据4.2 请求方法4.2.1 请求方法类型4.2.2…

C语言:输出所有“水仙花数”。“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身,如153=1^3 +5^3+3^3

分析: 在主函数 main 中,程序首先定义四个整型变量 m、a、b 和 c,并用于计算和判断水仙花数。然后使用 printf 函数输出提示信息。 接下来,程序使用 for 循环结构,从 100 到 999 遍历所有三位数。对于每个遍历到的数 m…

C#常见的设计模式-创建型模式

引言 在软件开发过程中,设计模式是一种被广泛采用的思想和实践,可以提供一种标准化的解决方案,以解决特定问题。设计模式分为三种类型:创建型模式、结构型模式和行为型模式。本篇文章将重点介绍C#中常见的创建型模式。 目录 引言…

python实现自动刷平台学时

背景 前一阵子有个朋友让我帮给小忙,因为他每学期都要看视频刷学时,一门平均需要刷500分钟,一学期有3-4门需要刷的。 如果是手动刷的话,比较麻烦,能否帮他做成自动化的。搞成功的话请我吃饭。为了这顿饭,咱…

Elasticsearch:什么是非结构化数据?

非结构化数据定义 非结构化数据是指未按照设计的模型或结构组织的数据。 非结构化数据通常被归类为定性数据,可以是人类或机器生成的。 非结构化数据是最丰富的可用数据类型,经过分析后,可用于指导业务决策并在许多其他用例中实现业务目标。…

正则表达式和awk

目录 一、正则表达式 1.正则表达式基本介绍 2.正则表达式分类 3.基本正则表达式分类 4.代表字符 5.表示次数 6.位置锚定 7.分组或其他 8.扩展正则表达式 二、awk 1.语法 2.选项 3.基础用法 4.内置变量 5.条件判断 6.数组 总结:本章主要介绍了正则表…

【C++】map与set

​👻内容专栏:C/C编程 🐨本文概括:关联式容器的介绍、set、multiset、map、multimap。 🐼本文作者:阿四啊 🐸发布时间:2023.11.27 一、关联式容器的介绍 在之前C的学习之中&#xf…

STM32入门--看门狗

一、独立看门狗简介 STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看…

【vue】a-table的斑马纹以及hover样式的修改:

文章目录 一、效果:二、实现(以jeecg为例): 一、效果: 二、实现(以jeecg为例): // 设置基数行样式 // .ant-table-tbody tr:nth-child(n) { // color: #fff; // }// hover时候每行…

如何使用 Java 在Excel中创建下拉列表

下拉列表(下拉框)可以确保用户仅从预先给定的选项中进行选择,这样不仅能减少数据输入错误,还能节省时间提高效率。在MS Excel中,我们可以通过 “数据验证” 提供的选项来创建下拉列表,但如果要在Java程序中…

Android应用程序开发实战篇----期末总结1

项目1(了解移动电子商务开发) 1,任务一:了解移动电子商务 移动电子商务:利用无线终端进行的电子商务活动。 移动电子商务的特点:方便,摆脱时空性,安全,潜在用户规模大,…

loadrunner-关联

loadrunner-关联 文章目录 关联自动关联手动关联手写脚本,关联登录token 关联 关联的作用是将服务器返回的数据保存为参数,后续接口中会用到该参数,当服务器数据发生变更时,脚本中的参数值也同时进行更新。 当脚本中需要服务器返…

Open Feign 源码解析(二) --- 如何发送http请求

Open Feign 源码解析二 如何发送http请求? 如何组件化? 定义接口 public interface Client {Response execute(Request request, Options options) throws IOException; }是否存在已有的方案? 1)rest template http client o…

5.9每日一题(幂级数求收敛区间:收敛半径不变的定理)

幂级数逐项求导逐项求积分(乘n或者除n),收敛半径不变 幂级数x换成xx0(即平移),收敛半径不变

手把手教学拥有自己的CLI

随着开发时间的增长,你积累的模版需要管理,不能老是复制粘贴。那么一个小小的cli 可以帮助你这个问题。它是你进行管理分类的管家,替你管理仓库和翻东西。 技术选型 NodeJSTSpnpmunbuild : unbuild 是基于rollup 配置更加单的打包工具chalk :…

【开源】基于Vue.js的无代码动态表单系统的设计和实现

项目编号: S 026 ,文末获取源码。 \color{red}{项目编号:S026,文末获取源码。} 项目编号:S026,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 动态类型模块2.2 动态文件模块2.3 动…

2023-11-27操作系统---进程—线程—实验

目录 2023-11-27操作系统_进程—线程_实验 5-10&#xff1a; 代码&#xff1a; 运行结果: 5-11 代码&#xff1a; 运行结果&#xff1a;​编辑 2023-11-27操作系统实验 5-10&#xff1a; 代码&#xff1a; #include<unistd.h> #include<stdio.h> #include…

力扣hot100 滑动窗口最大值 单调队列

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f37b; AC code class Solution {public int[] maxSlidingWindow(int[] nums, int k){int n nums.length;int[] res new int[n - k 1]; // 单调递减队列int[] q new int[n];// q数组维护的是元素在 nums 数组对应的下标int…

FFmepg 核心开发库及重要数据结构与API

文章目录 前言一、FFmpeg 核心开发库二、FFmpeg 重要数据结构与 API1、简介2、FFmpeg 解码流程①、FFmpeg2.x 解码流程②、FFmpeg4.x 解码流程 3、FFMpeg 中比较重要的函数以及数据结构①、数据结构②、初始化函数③、音视频解码函数④、文件操作⑤、其他函数 三、FFmpeg 流程1…