《数据结构》队列及其经典面试题

news/2024/5/3 21:05:15/文章来源:https://blog.csdn.net/qq_43575801/article/details/127032534

前言

上一篇讲了栈和栈的经典面试题,链接如下:

栈与栈的经典面试题

其实栈和队列是一码事,都是对只能再线性表的一端进行插入和删除。

因此,其实栈和队列可以互相转换!

一、队列的特点

先进先出的数据结构,元素从“队尾”添加到队列中,元素从“队首”出队列 (FIFO)

在这里插入图片描述


二、队列的实现

1.基于链表实现队列

现实生活中,有各式各样的“排队”操作。

同样的,队列也有基于数组实现的队列和基于链表实现的队列。

由于出队操作只能在队列的头部进行,若采用数组的方案,每次出队一个元素就得搬移剩下的所有元素向前移动一个单位。

此时采用链表的方案更加适合队列的结构。

2.核心操作

  • E poll() : 出队

  • offer(E e) : 入队


三、双端队列

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。

那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque -> Queue的子接口:

在这里插入图片描述

小技巧:

  • 大家以后无论使用的是栈还是队列,统一使用双端队列接口!
  • 不推荐使用Stack这个类,这个类已经是时代的弃子,效率很低,都是同步操作。
  • 双端队列的一个常用子类就是LinkedList。

在这里插入图片描述
在这里插入图片描述


四、循环队列

1.应用场景

  • 操作系统的生产消费者模型
  • MySQL数据库的InnoDB存储引擎中的redo日志。

2.实现

  1. 基本都是使用长度固定的数组实现,数组在实现队列时,若从数组头部删除元素需要频繁的移动后面的元素,带来的效率比较低。

  2. 出队和入队操作,使用两个引用,一个head,一个tail,添加元素在数组尾部添加,删除元素只需要移动head引用指向的地址即可(逻辑删除)。

循环队列就是使用长度固定的数组来实现,数组头部就是队首(head),数组的尾部就时队尾(tail)。数组[head…tail]是循环队列的有效元素。

例如:

在这里插入图片描述

  • head永远指向循环队列的第一个元素
  • tail永远指向循环队列有效元素的后一个位置

循环队列在删除元素时,不需要进行数据的搬移,当有新的元素在添加时就会覆盖掉之前的元素。

所谓的循环队列指的是当head或者tail引用走到数组末尾时,下一次再继续向后移动,其实是返回数组的头部继续操作。

3.判空和判满

由于tail指向的是有效数组后一个位置,所以当tail走到如图所示的head == tail 情况时:

在这里插入图片描述

此时我们没法区分当前循环队列到底是空还是满!!!

所以在循环队列中,需要浪费一个空间来判断队列是否已满,如下图所示:

在这里插入图片描述

结论:

  1. 此时当 (tail+1)%n == head 时,认为此时循环队列已满。
  2. head和tail的移动不能简单的+1,而要使用取模操作,取数组长度。
  3. 当head == tail 时 ,认为此时循环队列为空。

4.最后一个元素的索引

  • 除了tail这个引用指向0这个位置以外,其他情况的最后一个索引 = tail - 1
  • 当 tail = 0 时,最后一个元素就在数组的末尾,索引 = data.length - 1

在这里插入图片描述

代码如下:

int lastIndex = tail == 0 ? data.length -1 : tail - 1

五、队列的常见问题

1.用队列实现栈

链接如下:225.用队列实现栈

在这里插入图片描述


解题思路:

思路1:(双队列思路)

这个问题的本质和双栈实现最小栈是相同的思路,一定要保证其中一个队列就是进行实际元素存储的,另一个队列就是作为辅助操作。

q1永远是存储元素的队列,新元素添加到q2中,将此时q1中的所有元素出队再入队q2恰好就能实现添加顺序和出队顺序相反的操作

  1. 新元素永远入q2
  2. 将老元素q1依次出队再入q2 (这样就交换了元素的先后顺序)
  3. q1和q2交换引用

在这里插入图片描述

  • 其中一个队列q1永远都是存储元素的队列,栈的pop就是s1的poll,栈的peek就是s1的peek,栈的push就是s1的offer。 (所以整个题的核心操作就是push()

  • 以保证s1和栈的操作一一对应。

  • 另外一个队列就是作为辅助操作。

代码如下:

class MyStack {Deque<Integer> temp;Deque<Integer> q1;Deque<Integer> q2;public MyStack() {q1 = new LinkedList<>();q2 = new LinkedList<>();}public void push(int x) {q2.offer(x);while(!q1.isEmpty()){q2.offer(q1.poll());}temp = q1;q1 = q2 ;q2 = temp;}public int pop() {return q1.poll();}public int top() {return q1.peek();}public boolean empty() {return q1.isEmpty();}
}

思路2:(单队列思路)

在这里插入图片描述

  1. 先记录下当前队列中的元素个数n
  2. 将新元素直接入队
  3. 为了让新元素变成队首元素,连续出队n次(新元素的之前的所有元素都出队列,此时新元素变成了队首元素),再依次入队n次即可。

代码如下:

class MyStack {private Deque<Integer> queque;private int length=0;//1.先记录一下栈此时的元素个数public MyStack() {queque=new LinkedList<>();}public void push(int x) {queque.offer(x);//2.新元素直接入队//3.把新元素之前的元素挨个出队再入队,此时最新的元素就是队头元素for (int i=0;i<length;i++){queque.offer(queque.poll());}length++;}public int pop() {length--;return queque.poll();}public int top() {return queque.peek();}public boolean empty() {return queque.isEmpty();}
}

2.用栈实现队列

链接如下:用栈实现队列

在这里插入图片描述

解题思路:

思路1:(入队 - 时间复杂度为O(n),出队 - O(1))

定义s1永远是保存元素的栈

  1. 先将s1中的现有元素依次弹出放入s2
  2. 将新元素入s1 => 此时这个新元素就变成了s1的栈底(队尾元素)
  3. 将s2中的元素再依次弹回来(先进先出)

在这里插入图片描述

代码如下:

class MyQueue {Deque<Integer> s1;Deque<Integer> s2;public MyQueue() {s1 = new LinkedList<>();s2 = new LinkedList<>();}public void push(int x) {while(!s1.isEmpty()){s2.push(s1.pop());}s1.push(x);while(!s2.isEmpty()){s1.push(s2.pop());}}public int pop() {return s1.pop();}public int peek() {return s1.peek();}public boolean empty() {return s1.isEmpty();}
}

思路2:(入队 - 时间复杂度为O(1),出队-摊还复杂度O(1))

  1. push是正常push的,核心操作在pop里面
  2. push进s1的元素依次出栈再入s2栈的时候,出入顺序就会颠倒
  3. 根据上述特性,把s2的栈顶当作队首就行了,因为队列都是队首出队的。
  4. 每次pop先判断当前s2是否为空,若为空,则把s1中的元素全部出栈并且压进s2里面,此时s2的栈顶就是队首元素(先进先出)。若不为空,证明上一轮push进来的元素还没pop完,继续pop当前s2的栈顶就行。
class MyQueue {Deque<Integer> s1 ;Deque<Integer> s2 ;public MyQueue() {s1 = new LinkedList<>();s2 = new LinkedList<>();}public void push(int x) {s1.push(x);}public int pop() {if(s2.isEmpty()){while(!s1.isEmpty()){s2.push(s1.pop());}}return s2.pop();}public int peek() {if(s2.isEmpty()){while(!s1.isEmpty()){s2.push(s1.pop());}}return s2.peek();}public boolean empty() {return s1.isEmpty() && s2.isEmpty();}
}

总结

以上就是队列及其经典面试题的全部内容了,有帮助的话麻烦各位给个三连~~感谢!!!

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

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

相关文章

Android系统安全 — 2.0-移动终端栈溢出的保护机制设置

简介 操作系统提供了许多安全机制来尝试降低或阻止缓冲区溢出攻击带来的安全风险。例如 NX/DEP、 ASLR&#xff08;PIE&#xff09;、CANARY、FORTIFY、RELRO 等手段。 栈保护 1.NX/DEP Linux 和 Windows 平台都支持对非可执行代码的保护&#xff0c;在 Linux 平台中被称为…

【Mybatis框架】初识Mybatis

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 MyBatis1、MyBatis简介1.1、MyBatis历史1.2、MyBatis特性2. 搭建MyBatis2.1 创建一个Maven项目2.2 在项目下新建我们的MyBatis项目2.3 引入依赖2.4 创建MyBatis的核心配置文件2.5 创建mapper接口2.6 创建MyBatis的映射文件2.…

AWS 中文入门开发教学 34- MySQL@RDS - 准备工作 - VPC子网,安全组,DB子网组,参数组,选项组

知识点 建立RDS MySQL前的准备工作实战演习 VPC子网,安全组,DB子网组,参数组,选项组 VPC子网 Name: deeplearnaws-db-1cCIDR: 172.16.21.0/24 安全组 Name: deeplearnaws-db-sg <- 可以直接使用之前创建的,但生产环境时应只保留3306端口 DB子网组 Name: deeplearnaws-db-su…

JavaScript学习Day008(jQuery操作)

DOM操作分类 DOM操作分为三类 DOM Core&#xff1a;任何一种支持DOM的编程语言都可以使用它&#xff0c;如getElementById() HTML-DOM&#xff1a;用于处理HTML文档&#xff0c;如document.forms CSS-DOM&#xff1a;用于操作CSS&#xff0c;如element.style.color"gree…

【NLP】第12章 检测客户情绪以做出预测

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

JavaScript数组与对象

数组对象 「创建数组的两种方式」 1. 字面量方式var arr [1,"test",true];2. 实例化数组对象 new Array() var arr new Array(); 注意&#xff1a;上面代码中arr创建出的是一个空数组&#xff0c;如果需要使用构造函数Array创建非空数组&#xff0c;可以在创建数…

SpringCloud-19-Spring Cloud Hystrix介绍和服务端降级

8 Hystrix&#xff1a;Spring Cloud服务熔断与降级组件 8.1 分布式系统面临的问题 复杂分布式体系结构中的应用程序往往由多个服务组成&#xff0c;这些服务之间相互依赖&#xff0c;依赖关系错综复杂&#xff0c;每个依赖关系在某些时候将不可避免的失败&#xff01; 若一个…

最优化理论与方法2

凸优化问题&#xff1a; 对于最优化问题P&#xff1a; min f(x1, x2 , …,xn) s.t. : gi ( x1 , x2 , … , xn) < 0 , i 1 , … , m hi ( x1 , x2 , … , xn) 0 ,i 1 , … , l 1 . 记可行域为S { x ∈ Rn | gi(x)<0 , i1,…,m , hi(x)0 , i 1 , … , l.} 2.当f(x…

交通流域关键词

关键词&#xff1a; ●交通拥堵&#xff1a;traffic jam 或 traffic congestion ●元胞传输模型&#xff1a;cellular transport model 或 cell transport model(细胞传输模型) ●元胞自动机&#xff1a;cellular automata ●VSL(可变速度限制)&#xff1a;variable speed …

Python3 安装软件出现 cl.exe failed with exit status 2 错误

最近因项目需要&#xff0c;开始深入接触python。遇到的一些环境问题&#xff0c;分享下。 requirements.txt中包含一系列所需组件&#xff0c;部分组件安装会报cl.ext错误。 如错误问题&#xff1a;Python3 安装pycrypto 2.6.1 出现 cl.exe failed with exit status 2 错误 …

Android国际化多语言切换

关于App国际化&#xff0c;之前有讲到国际化资源、字符换、布局相关&#xff0c;想要了解的猛戳用力抱一下APP国际化。借着本次重构多语言想跟大家聊一下多语言切换&#xff0c;多语言切换对于一款国际化App来讲是重中之重&#xff0c;并非难事&#xff0c;但是若要做好也是一件…

LeetCode-136-只出现一次的数字

1、哈希表 利用哈希表记录每个元素和其出现的次数&#xff0c;最后遍历哈希表找到只出现一次的数字。缺点在于额外空间为O(n)O(n)O(n)。 class Solution { public:int singleNumber(vector<int> &nums) {unordered_map<int, int> hs;for (auto i: nums) {hs[…

疫情下低代码平台将是企业的曙光

全球疫情的爆发&#xff0c;加速了企业数字化转型进程&#xff0c;为了响应不断变化和增加的业务需求&#xff0c;需要充足的资金以及专业的开发人员才能够有效推行数字化管理。然而在这样的情景下&#xff0c;人员的缺少&#xff0c;时间的效率等问题&#xff0c;导致很多企业…

图像分类数据集(线性神经网络,需结合从零实现softmax回归一起学习)

文章目录图像分类数据集读取小批量整合所有组件小结图像分类数据集 导入必要的类包。 import torch import torchvision from torch.utils import data #torchvision是pytorch的一个图形库&#xff0c;它服务于PyTorch深度学习框架的&#xff0c;主要用来构建计算机视觉模型。…

Kafka设计原理——副本数据同步机制(watermark 和 leader epoch)

文章目录LEO更新机制follower副本LEO更新leader副本LEO更新HW更新机制follower更新HWleader更新HW使用HW衡量数据同步情况的缺陷LEO更新机制 follower副本LEO更新 Kafka设计了两套follower副本LEO属性&#xff0c;一套LEO值保存在follower副本所在的broker缓存上&#xff1b;…

详解 B2B 用户、组织、员工、角色

整理了一下 toB 多组织系统中常见的实体关系&#xff0c;往往在实际项目中这些基础模块是公司老前辈已经开发完成的&#xff0c;因此新人在此基础上开发一些相关的业务模块很容易被这些模糊不清的关系搞晕。 一、定义 user 用户&#xff0c;操作者的唯一标识&#xff0c;通常…

去中心化时代的创作者经济

所谓创作者经济&#xff0c;具体是指利用各种互联网工具&#xff0c;由个人或团体进行内容创作、分发及一系列与创作者相关服务下产生的经济收益。 这一概念也主要在当前的 web2互联网时代&#xff0c;并且有很多鲜明的案例凸显出了创作者经济的强大潜力&#xff0c;像我们熟知…

SpringCloud-20-Spring Cloud Hystrix客户端服务降级

8.5 客户端服务降级 通常情况下&#xff0c;我们都会在客户端进行服务降级&#xff0c;当客户端调用的服务端的服务不可用时&#xff0c;客户端直接进行服务降级处理&#xff0c;避免其线程被长时间、不必要地占用。沿用microservice-cloud-consumer-dept-openFeign客户端工程…

ConcurrentHashMap简单案例

concurrenthashmap 线程安全集合类 线程安全基本分类 线程安全集合类可以分为三大类&#xff1a; 遗留的线程安全集合如 Hashtable &#xff0c; Vector 使用 Collections 装饰的线程安全集合&#xff0c;如 Collections.synchronizedCollectionCollections.synchronizedLis…

【剑指offer】链表篇-含题目代码思路解析

【剑指offer】链表篇1. JZ6 从尾到头打印链表C注意2. JZ24 反转链表C(双指针法)注意3. JZ25 合并两个排序的链表C注意4. JZ52 两个链表的第一个公共结点C 【错误】C【正确】注意5. JZ23 链表中环的入口结点C注意6. JZ22 链表中倒数最后k个结点C注意7. JZ35 复杂链表的复制8. JZ…