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

数据结构——链表OJ题目讲解(1)

作者:几冬雪来

时间:2023年3月7日

内容:数据结构链表OJ题目讲解

题目来源:力扣和牛客

目录

前言:

刷题:

1.移出链表元素:

2.链表的中间结点:

3. 链表中倒数第k个结点:

结尾: 


前言:

在上一篇博客中我们对链表内容的讲解也就结束了,但是链表作为我们一个难度跨度较大的一个专题,因此单单看是不行的。在学习链表的过程中,如果要进一步提升自己,刷题是必不可少的一个环节。

刷题:

在学习数据结构的过程中,刷题能够提高我们写题的能力,帮助我们以后在在找工作的时候可以游刃有余,同时也可以检验出我们的不足之处,在写的时候还会有一些平常没有遇到的坑在等着我们,下面我就找来了力扣和牛客上找来一些有关链表的题目来讲解。 

1.移出链表元素:

 

题目要求删除链表中的某一数据,看似我们在写链表的代码中也有类似的操作,只不过它们还是有点不同。在我们书写的链表代码中,只是删除一次val而已,而这个题目则需要我们删除所有val,二者有所区别。

而在刷数据结构的题的时候,画图是我们一定要学会的一种技能。 那么这一题的运行是怎么样的呢?

因为是链表,因此一开始我们创建两个指针,prev指针指向我们第一个结点,cur指向第二个结点。 如果cur等于val的话,我们就将cur->next赋值给prev->next,然后将cur的值释放

这里我们将代码写出来,先创建两个空指针,一个置为空,一个指向第一个结点的位置,然后进行循环,循环条件是cur不为0。再下来就进行判断,如果cur的下一个结点不为val,则把cur赋予给prev,再让cur来到下一个结点

如果cur为val,则只需要将原cur的下一个结点的地址赋值给prev的next,后将cur释放。最后把prev->next赋值给cur,让它依旧指向prev的下一个结点。 

这里要注意最后应该是cur = prev->next,如果是cur = cur->next的话,我们会访问到空指针。 

代码到这里就结束了吗?我们运行出来看一看,但是这里的结果却十分出乎意料。

我们的案例并没有通过,这是为什么?这就需要分析一下了。我们从这个题目的用例中取一个用例来说明。

类似这个用例,假设第一个结点就是我们要删除的值,这个时候我们上面的代码if语句条件不满足进入else语句。然而因为if语句没有进行,我们的prev的值依旧为空,下面prev->next=cur->next就会出错。所以我们要对代码进行分开讨论。

就像上面的代码这样,如果第一个if语句条件不成立,那么就进入else语句中。这里我们在分支语句中再嵌套一个分支语句。如果我们的prev为空,那就说明第一个结点的值就是要删除的值。然后这里将我们的头结点改为cur->next,而后将cur释放,最后因为头结点的删除,因此要将head赋值给cur作为指向新的头结点的指针

结果证明我们的想法是正确的。

其实对于这道题目,我们还有其他的解决方法。这里我们可以将不是val的值尾插到新链表

像我们这张图,我们创建一个新链表newHead并在一开始将它置空。如果第一个结点不为val,则我们让cur = tail,作为我们新指针的头结点。而后cur向下移动,如果不为val则给新的链表然后tail也向下移动,如果不是则跳过这个值

依旧开始创建指针,下来函数循环。如何cur指向的不是val,则进入if语句中进行嵌套的分支语句。

而这里的嵌套的分支语句中,if语句只执行一次,当tail为空的时候,也就说明我们的新指针里面还没有值,这里就要将cur赋值给tail和newHead作为新指针的头结点。(尾插要赋值) 

再然后让tail->next指向cur也就是第二个结点,接下来tail向下走一步来到第二个结点的位置,cur向下走一步来到cur的下一个结点。 

如果找到val的值的话,我们就创建一个临时指针next,然后将cur下一个结点赋值给next,next就是cur的下一个结点,为的是保存我们这个结点。赋值完了之后我们将cur释放掉,然后将next赋值给cur。 

看似没有问题,但是实际上是会出错的,而链表中如果出问题的话,那么十有八九是野指针的存在

其实是这个代码出了问题,也不能说是问题,只能说不完整。那么为什么会不完整呢?在怎么的这个题目中最后一个数据是要删除的,然后在代码的这个地方,我们创建了一个临时变量来保存cur的下一个结点,然后将cur释放最后cur = next。但是我们tail->next依旧存在着原来没删除前值的地址,而后我们将其释放,这里就会变成一个空指针形式

而要解决这个问题也是十分简单。 

在循环结束后我们将tail->next置空即可,这样就避免了野指针的出现。 书写完了之后我们再次运行程序,但是很遗憾这里我们的代码函数存在问题。

 

从代码用例我们可以分析出,这是链表为空的情况,如果链表为空,这里我们程序的循环就不会运行。然后tail->next = NULL这个地方就出错了。

要修复这个问题其实也是十分的简单,只要在程序的开头对我们的链表是否为空进行判断即可。 

但是即使这样,我们的代码依旧有问题存在。 

当我们的代码全是7,删除的也是7的时候,这个时候代码也会出错。那个时候我们的代码会将全部结点删除掉了,没有结点尾插,newHead和tail依旧为空,还是tail->next = NULL这个地方的问题。 那么代码还是需要改进。

在这里我们用一个分支语句将它包裹住,如果结点全部删除tail为空,这个代码也不会执行程序也就不会出问题。再次运行程序看看结果。

终于在我们改了好多次之后,我们的代码终于运行成功了。下面我们就将我们的代码全部放上来。 

这道题我们到这里就结束了。下面还有一道题目需要我们解决。

2.链表的中间结点:

这道题是人我们求链表的中间结点的值,而解决这道题的方法有许多中。类似我们的最传统的方法,先计算链表的长度然后找中间值。 

又因为这道题目过于简单,因此这道题通常都有一些限制所在。例如:只能遍历一遍链表。如果是这样的话,那么上面的传统方法就不用了。 

同样的这道题也可以通过创建数组来解决,但是那种方法就类似于顺序表的写法,比起链表过于复杂。 为了比较快速的解决这道题,这里我们要了解一个解题方法——快慢指针。那么什么是快慢指针呢?

 

快慢指针的工作原理就类似我们上边这个图,一开始创立一个快指针和一个慢指针都指向头结点,而后开始移动快指针一次移动两步,慢指针则一次移动一步快指针的移动速度是慢指针的两倍,因此当指针fast走完的时候,slow刚刚好久到了链表的中间

然而这个代码还有另一个影响因素,那就是数组的个数为单数还是偶数。如果链表的结点个数是单数,则中间结点就只有一个,如果结点个数为偶数则中间结点有两个,依题得知如果中间结点个数为两个我们要取后面的那个结点

我们要将它进行分类讨论。 

先创建两个指针,两个指针都指向链表的头结点因为fast走的比slow指针要快,因此我们选用fast指针作为循环条件判断

两种判断的原理如图所示。而后就是循环,slow每次走一步,fast指针每次走两步,最后返回slow指针。运行起来看看结果。

通过测试可以看出我们的想法没有问题,也可以成功输出。

下一道题目则是来自我们的牛客网的题库。 

3. 链表中倒数第k个结点:

 

 这一题函数运用我们的快慢指针,只不过和上面的比较时间的快慢不一样,在这里我们比较的是个数。那么个数是怎么样快慢的呢?首先我们要知道一个点。

尾结点和倒数第k个结点之间的距离是k-1

那么解决这道题就有两种方法,我们画个图出来看看。

 

这就是我们的解题原理,既然倒数第k个结点和尾结点之间的距离是k-1。那么在快慢指针中我们就可以先让快指针先走k-1步,而后快指针和慢指针同时向后运行距离相差k-1,当我们的fast走到尾结点的时候,这个时候slow就是倒数第k个结点

也可以让fast先走k步,最后slow要在倒数第k个结点处的话,fast要指向空。两种方法都是可以的。而这个问题我采用了第二种方法

首先先对链表为空进行处理,接下来还是创建两个指针并都指向链表的头结点。然后先一个循环来让fast先走k步,最后再创建一个循环来让两个指针同时往后走,并在结束的时候返回slow的指针

但是这里我们的代码是不完全的,那它还存在什么问题呢? 在调试中我们可以看出如果在这里想要访问倒数第6个的结点,但是链表总共才5个数据,这样做就造成了空指针的问题。 那要怎么样修改呢?

 

改动的地方就是这里,如果fast为0了,我们直接返回空。但是我们的用例不止一个地方报错。在第二个用例处我们依旧报错了。

其实这里的问题更加容易解决。这里是因为的fast赋值比判断先执行,导致了第二个用例本来指向最后一个结点指向了最后一个结点后面的空。fast变为了空,因此我们要将这个判断语句调整到执行语句的上面

 

这个问题也就得到解决了。 

依旧我们将书写的代码放过来。

 

到这里这篇博客要刷的题就结束了。

结尾: 

通过今天刷的链表的题目,我们对链表的知识得到了进一步的提高,题目里面的有些坑也值得我们去深思,一些日常学习看起来微不足道的点,在正式写代码的时候可能就会出现致命的错误。如果想要更加提升自己链表能力的同学也可以多去找题目写。最后希望这篇博客能在写题的时候为各位提供帮助。

相关文章:

数据结构——链表OJ题目讲解(1)

作者:几冬雪来 时间:2023年3月7日 内容:数据结构链表OJ题目讲解 题目来源:力扣和牛客 目录 前言: 刷题: 1.移出链表元素: 2.链表的中间结点: 3. 链表中倒数第k个结点&#xff1…...

LeetCode_二分搜索_困难_154.寻找旋转排序数组中的最小值 II

目录1.题目2.思路3.代码实现(Java)1.题目 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums [0,1,4,4,5,6,7] 在变化后可能得到: 若旋转 4…...

面向对象设计模式:创建型模式之建造者模式

一、引入 Build:建造和构建具有建筑结构的大型物体 建楼:打牢地基、搭建框架、然后自下而上一层层盖起来。构建物体:通常需要先建造组成这个物体的各个部分,然后分阶段把它们组装起来 二、建造者模式 2.1 Intent 意图 Separate…...

集成学习boosting、bagging、stacking

目录 一、介绍 二、三种架构学习 (1)boosting (2)bagging (3)stacking 一、介绍: 对于单个模型来说很难拟合复杂的数,模型的抗干扰能力较低,所以我们希望可以集成多…...

数据模型(上):模型分类和模型组成

1.模型分类 ​ 数据模型是一种由符号、文本组成的集合,用以准确表达信息景观,达到有效交流、沟通的目的。数据建模者要求能与来自不同部门,具有不同技术背景,不同业务经验,不同技术水平的人员交流、沟通。数据建模者要了解每个人员的观点,并通过反馈证明理解无误,最终作…...

郑州轻工业大学2022-2023(2) 数据结构题目集 - ZZULI

6-1 线性表元素的区间删除 6-1 线性表元素的区间删除 分数 20 全屏浏览题目 切换布局 作者 DS课程组 单位 浙江大学 给定一个顺序存储的线性表,请设计一个函数删除所有值大于min而且小于max的元素。删除后表中剩余元素保持顺序存储,并且相对位置不能改变…...

【Python语言基础】——Python MySQL Drop Table

Python语言基础——Python MySQL Drop Table 文章目录Python语言基础——Python MySQL Drop Table一、Python MySQL Drop Table一、Python MySQL Drop Table 删除表 您可以使用 “DROP TABLE” 语句来删除已有的表: 实例 删除 “customers” 表: import…...

2023美团面试真题

面试前需要准备: 1. Java 八股文:了解常考的题型和回答思路; 2. 算法:刷 100-200 道题,记住刷题最重要的是要理解其思想,不要死记硬背,碰上原题很难,但 大多数的解题思路是相通的…...

【微信小程序开发全流程】篇章0:基于JavaScript开发的校园综合类微信小程序的概览

基于JavaScript开发的校园综合类微信小程序的概览 本文仅供学习,未经同意请勿转载 一些说明:上述项目来源于笔者我本科大三阶段2019年电子设计课程项目,在这个项目中,我主要是负责的部分有前端,前后端的对接&#xf…...

如何分析sql性能

1、前言 提到sql性能分析,可能都会想到explain,它在mysql里被称为执行计划,也就是说可以通过该命令看出mysql在通过优化器分析之后如何执行sql。mysql的内置优化器十分强大,它能帮我们把sql再次优化,以最低的成本去执…...

市场营销书籍推荐:《经理人参阅:市场营销》

要学好市场营销有什么好方法?答案是看书!比起碎片化地去阅读一些文章或看一些相关视频,读书来得更实在些。倘若能静下心来好好读上一本系统性的市场营销书籍,学好营销管理将不会再是一件难事。然而,问题的关键是&#…...

WPF 控件专题 MediaElement控件详解

1、MediaElement 介绍 MediaElement:表示包含音频和/或视频的控件。 MediaOpened在引发事件之前,ActualWidth控件将ActualHeight报告为零,因为媒体内容用于确定控件的最终大小和位置。 对于仅音频内容,这些属性始终为零。 对于固…...

基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇

本文目录前言做项目的三大好处强强联手(天狗组合)专栏作者简介专栏的优势后端规划1. SpringBoot 和 SpringCloud 的选择2. Mybatis 和 MybatisPlus 和 JPA 的选择3. MySQL 和 Mongodb 的选择4. Redis 和 RocketMQ5. 后端规划小总结后端大纲提前掌握的知识点一期SpringBoot二期S…...

循环队列的实现

我们知道队列的实现可以用单链表和数组,但是循环链表也可以使用这两种方式。首先我们来看看单链表:首先使用单链表,我们需要考虑循环队列的一些特点。单链表实现循环队列我们要考虑几个核心问题:首先我们要区别 解决 空 和 满 的问…...

MTK平台开发入门到精通(休眠唤醒篇)休眠唤醒LPM框架

文章目录 一、lpm驱动源码分析二、设备属性调试文件沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍 lpm 驱动源码分析。 mtk 平台下,其默认的 lpm 机制的源码位置:drivers/misc/mediatek/lpm/ 一、lpm驱动源码分析 目录:drivers/misc/mediatek/lpm/…...

ThreadLocal详解

一、ThreadLocal简介 1、简介 ThreadLocal叫做线程变量,它是一个线程的本地变量,意味着这个变量是线程独有的,是不能与其他线程共享的。这样就可以避免资源竞争带来的多线程的问题。 即 ThreadLocal类用来提供线程内部的局部变量&#xff0…...

利用Cookie劫持+HTML注入进行钓鱼攻击

目录 HTML注入和cookie劫持: 发现漏洞 实际利用 来源 HTML注入和cookie劫持: HTML注入漏洞一般是由于在用户能够控制的输入点上,由于缺乏安全过滤,导致攻击者能将任意HTML代码注入网页。此类漏洞可能会引起许多后续攻击&#…...

【接口汇总】常用免费的API

短信API 短信验证码:可用于登录、注册、找回密码、支付认证等等应用场景。支持三大运营商,3秒可达,99.99%到达率,支持大容量高并发。 通知短信:当您需要快速通知用户时,通知短信是最快捷有效的…...

数字信号处理知识点

数字信号处理知识点1 频谱图中,横坐标取值范围的含义2 MATLAB常用函数2.1 波形产生2.2 滤波器分析2.3 滤波器实现2.4 线性系统变换2.5 滤波器设计2.5.1 FIR滤波器2.5.2 IIR滤波器2.6 Transforms(变换)2.7 统计信号处理和谱分析2.8 Windows(窗函数)2.9 Parametric Mo…...

计算机网络第八版——第三章课后题答案(超详细)

第三章 该答案为博主在网络上整理,排版不易,希望大家多多点赞支持。后续将会持续更新(可以给博主点个关注~ 第一章 答案 第二章 答案 【3-01】数据链路(即逻辑链路)与链路(即物理链路)有何区…...

九龙证券|磷酸亚铁锂是什么?磷酸亚铁锂的特点和性能介绍

磷酸亚铁锂是一种新式锂离子电池电极资料,化学式:LiFePO4,磷酸亚铁锂为近来新开发的锂离子电池电极资料,首要用于动力锂离子电池,作为正极活性物质运用,人们习气也称其为磷酸铁锂。 磷酸亚铁锂的特色和功能…...

3D目标检测(二)—— 直接处理点云的3D目标检测网络VoteNet、H3DNet

前言上次介绍了基于Point-Based方法处理点云的模块,3D目标检测(一)—— 基于Point-Based方法的PointNet点云处理系列,其中相关的模块则是构成本次要介绍的,直接在点云的基础上进行3D目标检测网络的基础。VoteNet对于直接在点云上预…...

Java学习-IO流-常用工具包(hutool)

Java学习-IO流-常用工具包(hutool) hutool工具包 DateUtil:日期时间工具类 TImeInterval:计时器工具类 StrUtil:字符串工具类 HexUtil:16进制工具类 HashUtil:Hash算法类 ObjectUtil&#xff1…...

【LeetCode】1. 两数之和

题目链接:https://leetcode.cn/problems/two-sum/ 📕题目要求: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入…...

【数值模型环境搭建】Intel编译器安装

Intel编译器在数值模型编译中被广泛使用,它有一个很好的地方是自带Mpich,不需要额外安装。本文介绍Intel2018.1.163版本的安装。 1、安装包获取 Intel编译器可从官网下载下载: https://www.intel.cn/content/www/cn/zh/homepage.html 或者…...

操作VMware vCenter Converter 实现物理机迁移到虚拟机

实验目的:熟练VMware虚拟化项目中,物理机向ESXI5迁移操作过程。 1、打开VMwarevCenterConverterStandalone5.0软件,按“转换计算机”。 2、选择“已打开电源的计算机”。并输入远程要连接迁移物理机IP地址,登录帐户和密码。 然后…...

hutool XML反序列化漏洞(CVE-2023-24162)

漏洞简介 Hutool 中的XmlUtil.readObjectFromXml方法直接封装调用XMLDecoder.readObject解析xml数据,当使用 readObjectFromXml 去处理恶意的 XML 字符串时会造成任意代码执行。 漏洞复现 我们在 maven 仓库中查找 Hutool ​https://mvnrepository.com/search?…...

Java简单认识泛型——图文详解

写在开头:想必大家和博主一样,在以往学习JavaSE的语法中,遇到了一个陌生的词——泛型,博主当时很好奇,什么是泛型呢?即使是学完了JavaSE,这个问题都没有解决,只能在百度查阅了解关于泛型的一些皮…...

AcWing171.送礼物

题目描述 达达帮翰翰给女生送礼物,翰翰一共准备了NNN 个礼物,其中第 iii 个礼物的重量是 G[i]G[i]G[i]。 达达的力气很大,他一次可以搬动重量之和不超过 WWW 的任意多个物品。 达达希望一次搬掉尽量重的一些物品,请你告诉达达在…...

领域驱动设计-架构篇

目录 1、软件架构概述 1.1 软件架构概念 1.2 软件架构分类 1.3 软件架构模式 1.4 软件架构风格 2、领域驱动软件架构 2.1 架构风格 六边行架构(领域驱动设计首选) 为什么选择REST架构 松耦合 可伸缩性 易用性 约束性 2.2 架构模型 命令和…...