数据结构刷题训练——链表篇(二)

目录

前言

1.题目一:链表分割

1.1 思路

1.2 分析

 1.3 题解

2. 题目二:相交链表

2.1 思路

2.2 分析

2.3 题解

3. 题目三:环形链表

3.1 思路

3.2 分析

3.3 题解

总结


前言

        本期继续分享链表相关的OJ题目,在这个专栏博客中,我们将提供丰富的题目资源和解题思路,帮助读者逐步提高解题能力。同时,我们也将分享一些刷题技巧和经验,帮助读者更加高效地进行刷题训练。通过持之以恒的努力和不断的实践,相信读者可以在数据结构领域取得长足的进步。


1.题目一:链表分割

题目描述:

 题目链接:

链表分割icon-default.png?t=N6B9https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

1.1 思路

        这道题目没有示例,这也是这道题的难点之一,我们只根据题意自己寻找示例,进行分析。题目的意思是说,给一个链表,给一个x值,把小于x的插入到x前边,大于x的插入到x的后边,且不可以打乱原链表中的次序(链表中的数据大小为乱序)。理解了题意,大家可以先自己思考一下解题思路。

        对于这道题的要求我们可以这样做:遍历原链表,将大于等于x的尾插到一个新链表,小于x的尾插到一个新链表,最后将两个链表合并。

1.2 分析

        这道题思路虽然非常简单,但是在实际编写代码时会有很多的坑。例如要考虑链表为NULL的情况,如果原链表中的所有值都大于x或小于x那就会造成两个链表中,其中一个链表为NULL。

 假设原链表为:

 x值为3,那我们就可以把原链表分割成以下两个链表:

         这道题目有两种方法,一种是使用带头节点的链表,一种是使用不带头节点的链表。对于链表掌握不熟悉的,本人推荐使用带头节点的链表,当然带头节点的链表对于这道题也可以简化代码。如果没有带头节点,那我们在初始化后尾插时就需要进行特殊处理。相对比较麻烦,所有我们这里推荐使用带头链表。

        如果带头结点两链表就是这样的:

 将两个链表合并时也不需要特殊处理可以直接连接,如下图:

 不用担心头节点怎么办,两个头节点最后会被销毁,销毁之后就是我们所需要的链表了。

         就算是第一个链表为空,也可以搞定:

         连接的时候也不需要特殊处理,最后销毁两个头节点即可。

 1.3 题解

根据分析的思路,我们对代码进行编写:

ListNode* partition(ListNode* pHead, int x) {struct ListNode* head1,*head2,*tail1,*tail2;head1=tail1=(struct ListNode*)malloc(sizeof(struct ListNode));//创建两个头节点head2=tail2=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* cur=pHead;    while(cur)                    //遍历原链表{if(cur->val < x)          //小于x就尾插到链表1{tail1->next=cur;tail1=tail1->next;}else                      //大于等于x就尾插到链表2{tail2->next=cur;tail2=tail2->next;}cur=cur->next;            }tail1->next=head2->next;      //将两个链表合并tail2->next=NULL;struct ListNode* head=head1->next;free(head1);free(head2);return head;                  //最后返回链表1的第一个节点}

2. 题目二:相交链表

题目描述:

 示例:

 题目链接:

相交链表icon-default.png?t=N6B9https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

2.1 思路

        这道题目的解题思路就简单了,但要注意链表长度不同的情况。当两个节点的节点个数不相同时,指向长链表的指针要先走它们节点个数的差值步。然后开始一一对比,直到遇到相交节点为止。

2.2 分析

        链表相交并不是像直线那样交叉相交,单链表中,一个节点只能指向一个节点,所有这里的链表相交是如下图的情况:

 总体分 3 步:

  • 先遍历两个链表得到两个链表的长度。
  • 长的链表先走差距步(len1-len2)。
  • 开始遍历两个数组,直到相交点,返回相交的节点

2.3 题解

整理完思路后,根据分析的思路进行编写代码:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{struct ListNode* curA=headA,*curB=headB;int lenA=1,lenB=1;while(curA->next){curA=curA->next;lenA++;}while(curB->next){curB=curB->next;lenB++;}if(curA!=curB)        //如果遍历到最后两个链表的尾节点不是同一个节点就说明不相交。{return NULL;}int t= abs(lenA-lenB);//求出差距步  abs是求绝对值的函数struct ListNode* longlist=headA, *shortlist=headB;if(lenB>lenA)           //这里先假设链表A长,如果不是链表A长就交换一下,简化代码{longlist=headB;shortlist=headA;}while(t--)              //长的链表走差距步{longlist=longlist->next;}while(longlist!=shortlist)//两链表同时遍历{longlist=longlist->next;shortlist=shortlist->next;}return longlist;          //循环停止时指向的节点就是第一个相交节点,返回它们两个任意一个
}

3. 题目三:环形链表

题目描述:

 示例:

 题目链接:

环形链表icon-default.png?t=N6B9https://leetcode.cn/problems/linked-list-cycle/description/

3.1 思路

         我们知道循环链表,循环链表的尾指向链表的头,遍历一遍之后会回到链表的头,但这道题属于带环链表,带环链表的尾不一定连接着头,它可能连接着任意节点。带环链表的题目属于链表中较为复杂的题目,那要如何判断一个链表是否带环呢?

        首先我们知道,带环链表在向后遍历的时候,一定会回到入环点,比较链表中的节点是否为入环时的节点就可以了,但是问题来了,我们怎么知道哪个是开始入环的节点?不知道入环的节点又怎么比较是否是同一个节点。显然传统的思路行不通,那我们就来换一种方法。

        这里我们就可以使用快慢指针的方法,一个指针走的快一个指针走的慢,当快的指针再次与慢指针相遇,那就说明这个链表一定是带环链表。

3.2 分析

        带环链表的入环节点可能是任意节点:

         它也可以指向它自己。

        这里我们可以使用快慢指针的方法,使用快指针来追击慢指针,当快指针与慢指针再次相遇,这就说明这个链表一定为带环链表,但是如果快指针走到了NULL,这就说明这个链表不是带环链表。

3.3 题解

 根据分析的思路,我们整理一下,形成代码:

bool hasCycle(struct ListNode *head) {struct ListNode* fast,*slow;fast=slow=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(fast==slow){return true;}}return false;
}

         题解也是非常简单。对于带环链表,今天这道题目属于热身,下期我会专门出一期带环链表的题目。


 

总结

        最后,感谢你的阅读和支持。希望你在这个数据结构的学习旅程中能够获得满满的收获和成就感。愿我们共同努力,不断探索和挑战,成为数据结构领域的行家里手!

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

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

相关文章

python高阶技巧

目录 设计模式 单例模式 具体用法 工厂模式 优点 闭包 案例 修改闭包外部变量 闭包优缺点 装饰器 装饰器原理 装饰器写法 递归 递归的调用过程 递归的优缺点 用递归计算阶乘 设计模式 含义&#xff1a;设计模式是一种编程套路&#xff0c;通过这种编程套路可…

Selenium 根据元素文本内容定位

使用xpath定位元素时&#xff0c;有时候担心元素位置会变&#xff0c;可以考虑使用文本内容来定位的方式。 例如图中的【股市】按钮&#xff0c;只有按钮文本没变&#xff0c;即使位置变化也可以定位到该元素。 xpath内容样例&#xff1a; # 文本内容完全匹配 //button[text(…

c++游戏制作指南(三):c++剧情类文字游戏的制作

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到静渊隐者的csdn博文&#xff0c;本文是c游戏制作指南的一部&#x1f35f; &#x1f355;更多文章请点击下方链接&#x1f355; &#x1f368; c游戏制作指南&#x1f3…

荐读 | 《揭秘云计算与大数据》

当我们回顾过去几十年的科技进步时&#xff0c;云计算和大数据在现代科技发展史上无疑具有里程碑式的意义&#xff0c;它们不仅改变了我们的生活方式&#xff0c;而且对各行各业产生了深远的影响。 在这个数字化时代&#xff0c;云计算和大数据技术已经成为推动全球发展的关键…

java中的hashmap和concurrenthashmap解析

hashmap的初始化数组大小为16&#xff0c;如果发生哈希冲突的时候在当前的索引后面采用头插法以链表的形式继续插入节点。 concurrenthashmap的结构图如下所示&#xff1a; 本身不是16个节点吗&#xff1f;这里分为两个长度为4的数组&#xff0c;变成了4*4总共16个节点&#x…

LouvainMethod分布式运行的升级之路

1、背景介绍 Louvain是大规模图谱的谱聚类算法&#xff0c;引入模块度的概念分二阶段进行聚类&#xff0c;直到收敛为止。分布式的代码可以在如下网址进行下载。 GitHub - Sotera/spark-distributed-louvain-modularity: Spark / graphX implementation of the distri…

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证,纯代码操作

引言&#xff1a;所谓http协议&#xff0c;本质上也是基于TCP/IP上服务器与客户端请求和应答的标准&#xff0c;web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

2023上半年手机及数码行业分析报告(京东销售数据分析)

2023年上半年&#xff0c;手机市场迎来复苏&#xff0c;同环比来看&#xff0c;销量销额纷纷上涨。 而数码市场中&#xff0c;各个热门品类表现不一。微单相机及智能手表同比去年呈现增长态势&#xff0c;而笔记本电脑市场则出现下滑。 基于此现状&#xff0c;鲸参谋发布了20…

Cesium 加载ArcGIS Server切片服务错级问题

1.首先上官方api说明 ArcGisMapServerImageryProvider - Cesium Documentation 里面没有 zoomoffset参数!!! 2.如果按照互联网栅格切片规则 3857、4326、4490常用切片层级参数,则直接加载显示地图 viewer.imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerI…

数据结构——AVL树

文章目录 一.AVL树的定义二.AVL树的插入三.插入后更新平衡因子四.AVL树的旋转1.左单旋2.右单旋3.先左单旋再右单旋4.先右单旋再左单旋 五.AVL树的性能分析六.检查是否满足AVL树七.源码 一.AVL树的定义 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉…

Python识别抖音Tiktok、巨量引擎滑块验证码识别

由于最近比较忙&#xff0c;所以本周搞了一个相对简单的验证码&#xff0c;就是抖音Tiktok的滑块验证码&#xff0c;这也是接到客户的一个需求。这种验证码通常在电脑端登录抖音、巨量引擎的的时候出现。 首先看一下最终的效果&#xff1a; 验证码识别过程 1、利用爬虫采集图…

mysql再docker中运行,直接在实体机上运行mysql命令初始化数据库数据

背景 项目上我们使用docker安装mysql&#xff0c;项目启动的时候需要利用sql语句初始化数据。 直接在实体上是识别不到mysql命令的。 实现方式 实现方式1&#xff1a;在docker容器内部执行sql语句 1. 将sql文件上传到容器内 docker cp /root/1.sql d5:/home/ 说明&#…