【初阶数据结构与算法】链表刷题之链表分割、相交链表、环形链表1、环形链表I、环形链表II
文章目录
- 一、链表分割
- 二、相交链表
- 三、环形链表I
- 四、环形链表||
一、链表分割
题目链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70
我们来看看链表分割的题目描述和它给出的函数:
这个题虽然是以C++形式来做,但是不用担心,我们知道在哪里写代码就可以了,就是题目提示的地方,这个属于C++类的知识,我们在后面的C++部分会详细介绍
接着我们回归正题,题目要求我们将链表分割开来,值小于x的节点要放在链表的左边,值大于等于x的节点要放在链表的右边,这个题该怎么做呢?
方法和双指针的算法有点类似,但是又不完全相同,我们可以创建两个新链表,一个存放比x小的节点,另一个存放比x大或者和x相等的节点,最后让小链表和大链表首位相连即可
这里我们要注意的是,如果我们创建的两个链表初始为空会发生什么,我们每次插入节点时,都要判断要插入的链表是否为空,空和非空的操作不一致,加上我们有两个新链表,操作起来更加的繁琐
所以我们还是用上之前学过的知识,怎么保证一个链表默认不为空?没错,就是在初始情况下创建一个哨兵位节点占位,它不存放有效的数据,单纯用来占位,这样我们在插入节点时就不需要去判断链表是否为空了
最后我们再来大致梳理一下解题思路,就是创建大小链表,同时创建哨兵位占位,然后遍历原链表,把值小于x的节点放在小链表,其它的放在大链表,最后让小链表和大链表首尾相连即可,题解如下:
ListNode* partition(ListNode* pHead, int x) {ListNode* lesshead, *lesstail;ListNode* greaterhead, *greatertail;lesshead = lesstail = (ListNode*)malloc(sizeof(ListNode));greaterhead = greatertail = (ListNode*)malloc(sizeof(ListNode));ListNode* pcur = pHead;while(pcur){if(pcur->val < x){lesstail->next = pcur;lesstail = pcur;}else {greatertail->next = pcur;greatertail = pcur; }pcur = pcur->next;}//小链表的尾巴连接大链表的头//大链表哨兵位的下一个节点是真正的头lesstail->next = greaterhead->next;//为了避免形成环,把尾节点的next指针置为空greatertail->next = NULL;//要返回的头就是小链表哨兵位后真正的头ListNode* ret = lesshead->next;//资源清理工作free(lesshead);free(greaterhead);lesshead = NULL;greaterhead = NULL;return ret;}
我们提交一下试试:
二、相交链表
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/description/
我们来看看题目描述和给出的函数:
题目的要求就是给我们两个链表,然后让我们判断这两个链表是否相交,如果相交就返回相交的节点,否则就返回空
我们要注意到相交链表的特殊性,直线相交的话它们还会朝着不同的方向继续延伸,想象一下链表相交以后会怎么样,它们相交后一定只有一个方向,而不会像直线相交那样有多个方向,因为如果它们相交,那么相交节点的next指针指向同一个节点,如此循环下去自然就只有一个方向
那么问题好像要简单一些了,我们遍历两个链表,看看有没有相同的节点不就好了,可是还是有一个问题,我们看看题目的第一个示例就知道了:
这个问题就是两个链表的长度可能不同,在上面的示例中,如果同时开始遍历的话,当链表A遍历到相交节点8时,链表B才遍历到节点1,这样它们差一位就永远不能相等,也就找不到相交节点
那有没有什么办法让它们从同一起跑线出发呢?我们能让小的那个链表变长,但是可以让大链表往前走两步呀,比如上图,我们就可以让大链表先往前走一步到6节点,然后它们在同一起跑线往后遍历就可以找到相交节点了
问题是我们要怎么知道那个链表大,大多少,知道了这两个条件后,我们就可以让大链表提前走它们的长度差距,然后同时对他们进行遍历,为了知道它们的大小,我们可以定义两个整型计数器来计算它们的大小
然后根据大小来判断谁大谁小,然后让大链表往前走它们的长度差距,最后让大小链表同时往前遍历,如果遇到相同的节点说明它们相遇了,返回这个节点就可以了,但是如果遍历到尾结点后还没有相同的节点,说明两个链表不相交,返回空,题解如下:
typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{//创建两个节点指针遍历链表ListNode* pcurA = headA;ListNode* pcurB = headB;int countA = 0, countB = 0;while(pcurA){countA++;pcurA = pcurA->next;}while(pcurB){countB++;pcurB = pcurB->next;}//假设法来判断链表大小//假设A链表更小//如果假设错误后面计算出大小后进行修改ListNode* lesslist = headA;ListNode* greaterlist = headB;//如果A的节点个数大于B,那么进行修改if(countA > countB){lesslist = headB;greaterlist = headA;}//接着让大的链表往后走间隔大小//首先使用绝对值函数求间隔大小int size = abs(countA - countB);while(size--){greaterlist = greaterlist->next;}//此时两个链表在同一起跑线,长度一样//然后再往后遍历while(lesslist){if(lesslist == greaterlist){return lesslist;}lesslist = lesslist->next;greaterlist = greaterlist->next;}//出了循环说明没有相交,返回NULLreturn NULL;
}
最后提交一下代码:
三、环形链表I
题目链接:https://leetcode.cn/problems/linked-list-cycle/description/
我们来看看环形链表I的题目描述与示例:
我们首先要知道链表带环是什么意思,就是它的尾结点的next指针不指向空了,而是指向链表中的某个节点,以此成为带环链表
这个题还较为简单,只需要我们判断链表是否有环,而不需要我们找出入环节点,做这个题需要用到一个结论,这里我就直接说出来了,如果对它的证明过程感兴趣可以自行去了解一下,当然也可以私信我,我会及时给出解答,这里就不多证明了
在这里我们需要用到快慢指针,结论就是慢指针一次走一步,快指针一次走两步,如果链表带环,那么快指针和慢指针一定会在环内相遇,如果不带环那么循环直接结束了,有了这个结论我们写起来就简单多了,如下:
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head)
{ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){return true;}}return false;
}
我们提交代码试试:
四、环形链表||
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/
我们来看看环形链表II的题目描述和示例:
这个题和上一个题的最大区别就是,这个题不仅要求我们判断链表是否是一个带环链表,如果带环还要我们找出入环的第一个节点,这个就比较难了
这里我们还是使用一个结论,相关的证明可以自行了解,也可以私信我,我会及时给出解答,这里就不多证明了
结论还是需要用到快慢指针,如果链表带环,那么快慢指针一定就会在环内相遇,并且相遇节点到入环节点的距离,和头结点到入环节点的距离相等
通俗一点说就是,当快慢指针在环内相遇后,让头结点和慢指针同时往前,并且每次走一步,那么当头结点和慢指针相遇时,相遇节点就是入环节点
因为此时头结点和慢指针走的步数相同,还相遇了,根据上面的结论就可以说明相遇节点就是入环节点,是不是特别神奇,接着我们就根据这个结论来写代码,如下:
typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head)
{ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){//进入这里说明链表带环ListNode* pcur = head;while(pcur){//判断是否相等//不相等循环的往前走if(pcur == slow){return pcur;}pcur = pcur->next;slow = slow->next;}}}//出了循环,说明链表不带环return NULL;
}
提交代码:
那么今天的刷题分享就到这里啦,如果有什么疑问欢迎提出,题目中使用的相关证明也可以直接问我
最后感谢大家的观看,bye~
相关文章:

【初阶数据结构与算法】链表刷题之链表分割、相交链表、环形链表1、环形链表I、环形链表II
文章目录 一、链表分割二、相交链表三、环形链表I四、环形链表|| 一、链表分割 题目链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70 我们来看看链表分割的题目描述和它给出的函数: 这个题虽然是以C形式来做࿰…...

【STL】set,multiset,map,multimap的介绍以及使用
关联式容器 在C的STL中包含序列式容器和关联式容器 1.关联式容器:它里面存储的是元素本身,其底层是线性序列的数据结构,比如:vector,list,deque,forward_list(C11)等 2.关联式容器里面储存的…...

新能源二手车交易量有望破百万,二手车市场回暖了吗?
这些年,伴随着新能源汽车市场的高速发展,各种新能源车的二手车也在逐渐增加,不过之前的二手车市场相对比较冷清,就在最近一则新闻传出新能源二手车交易量有望破百万,二手车市场这是回暖了吗? 一、新能源二手…...

哈佛商业评论 | 项目经济的到来:组织变革与管理革新的关键
在21世纪,项目经济(Project Economy)逐步取代传统运营,成为全球经济增长的核心动力。项目已不再是辅助工具,而是推动创新和变革的重要载体。然而,只有35%的项目能够成功,显示出项目管理领域存在巨大的改进空间。本文将详细探讨项目经济的背景、项目管理的挑战,以及适应…...

web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
如果你使用 window.open() 方法打开 PDF 文件,但浏览器不是预览而是下载文件,这可能是由于以下几个原因: 服务器配置:服务器可能将 PDF 文件配置为下载而不是预览。例如,服务器可能设置了 Content-Disposition 响应头…...

【GeekBand】C++设计模式笔记12_Singleton_单件模式
1. “对象性能” 模式 面向对象很好地解决了 “抽象” 的问题, 但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。典型模式 SingletonFlyweight 2. Si…...

Pyhon基础数据结构(列表)【蓝桥杯】
a [1,2,3,4,5] a.reverse() print("a ",a) a.reverse() print("a ",a)# 列表 列表(list)有由一系列按照特定顺序排序的元素组成 列表是有顺序的,访问任何元素需要通过“下标访问” 所谓“下标”就是指元素在列表从左…...

Linux篇(权限管理命令)
目录 一、权限概述 1. 什么是权限 2. 为什么要设置权限 3. Linux中的权限类别 4. Linux中文件所有者 4.1. 所有者分类 4.2. 所有者的表示方法 属主权限 属组权限 其他权限 root用户(超级管理员) 二、普通权限管理 1. ls查看文件权限 2. 文件…...

深入理解 Spark 中的 Shuffle
Spark 的介绍与搭建:从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交:本地与集群模式全解析-CSDN博客 Spark on YARN:Spark集群模式…...

leetcode-8-字符串转整数
题解: 代码:...

SQL注入注入方式(大纲)
SQL注入注入方式(大纲) 常规注入 通常没有任何过滤,直接把参数存放到SQL语句中。 宽字节注入 GBK 编码 两个字节表示一个字符ASCII 编码 一个字节表示一个字符MYSQL默认字节集是GBK等宽字节字符集 原理: 设置MySQL时错误配置…...

OpenCV基础(1)
1.图像读写与窗口显示 1.1.imread读取图像文件 Mat cv::imread(const string &filename,int flags IMREAD_COLOR); filename:要读取的图像文件名flags:读取模式,可以从枚举cv::ImreadModes中取值,默认取值是IMREAD_COLOR&am…...

【freertos】FreeRTOS信号量的介绍及使用
FreeRTOS信号量 一、概述二、PV原语三、函数接口1.创建一个计数信号量2.删除一个信号量3.信号量释放4.在中断释放信号量5.获取一个信号量,可以是二值信号量、计数信号量、互斥量。6.在中断获取一个信号量,可以是二值信号量、计数信号量7.创建一个二值信号…...

React Native 全栈开发实战班 - 图片加载与优化
在移动应用中,图片加载与优化 是提升用户体验和减少资源消耗的重要环节。图片加载不当可能导致应用卡顿、内存泄漏甚至崩溃。本章节将介绍 React Native 中常用的图片加载方法,包括 Image 组件的使用、第三方图片加载库(如 react-native-fast…...

Golang云原生项目:—实现ping操作
熟悉报文结构 ICMP校验和算法: 报文内容,相邻两个字节拼接到一起组成一个16bit数,将这些数累加求和若长度为奇数,则将剩余一个字节,也累加求和得出总和之后,将和值的高16位与低16位不断求和,直…...

mysql如何查看当前事务的事务id
-- 开启一个事务,但不执行写操作 START TRANSACTION; -- 查询 InnoDB 事务信息 SELECT * FROM information_schema.innodb_trx;在 MySQL 的 MVCC (多版本并发控制) 中,事务 ID (Transaction ID) 是由 InnoDB 存储引擎分配的,它的分配机制与事…...

在linux里如何利用vim对比两个文档不同的行数
在Linux中,可以使用vimdiff命令来对比两个文档中不同的行。首先确保你的系统中安装了vim编辑器。 打开终端,使用以下命令来启动vimdiff: vimdiff file1 file2 这里file1和file2是你想要对比的两个文件的路径。 vimdiff会以并排方式打开两…...

深入解析Python中的逻辑回归:从入门到精通
引言 在数据科学领域,逻辑回归(Logistic Regression)是一个非常重要的算法,它不仅用于二分类问题,还可以通过一些技巧扩展到多分类问题。逻辑回归因其简单、高效且易于解释的特点,在金融、医疗、广告等多个…...

【数据库】mysql数据库迁移前应如何备份数据?
MySQL 数据库的备份是确保数据安全的重要措施之一。在进行数据库迁移之前,备份现有数据可以防止数据丢失或损坏。以下是一套详细的 MySQL 数据库备份步骤,适用于大多数情况。请注意,具体的命令和工具可能因 MySQL 版本的不同而有所差异。整个…...

C语言——鸡兔同笼问题
没注释的源代码 #include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { int tou 10; i…...

数据结构王道P234第二题
#include<iostream> using namespace std; int visit[MAxsize]; int color[MaxSize];//1表示红,2表示白; bool dfs(Graph G, int i){visit[i]1;ArcNode *p;bool flag1;for(pG.vertices[i].firsrarc; p ; pp->next){int jp->adjvex;if(!visi…...

层归一化和批归一化
层归一化是针对某一样本的所有特征,批归一化是针对所有样本的某一特征。 计算公式:(当前值 - 均值)/ 标准差。 作用:缓解梯度消失和梯度爆炸的问题,并提高网络的泛化性能。 为什么Transform和BERT中使用层归…...

Spring Cloud Gateway 网关
微服务网关 Spring Cloud Gateway https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories Spring Cloud 在版本 2020.0.0 开始,去除了 Zuul 网关的使用,改用 Spring Cloud Gateway 作为网关…...

LabVIEW中的UDP与TCP比较
在LabVIEW中,UDP和TCP可以用于不同的网络通信场景,开发者可以根据需求选择合适的协议。以下是结合LabVIEW开发时的一些比较和应用场景: 1.TCP在LabVIEW中的应用: 可靠性高的场景:当开发一个对数据传输的准确性和完整…...

半导体器件与物理篇3 P-N结
热平衡时的PN结 pn结的定义:由p型半导体和n型半导体接触形成的结 pn结的特性和关键变量包括:整流性(即电流单向导通的特性)、平衡费米能级(费米能级 E F E_F EF为常数, d E F d x 0 )、内建电势 \frac…...

深入剖析String类的底层实现原理
嘿嘿,家人们,今天咱们来模拟实现string,好啦,废话不多讲,开干! 1:string.h 1.1:构造函数与拷贝构造函数 1.1.1:写法一 1.1.2:写法二(给缺省值) 1.2:赋值运算符重载与operatror[]获取元素 1.3:容量与迭代器 1.4:reserve与resize 1.5:清空与判断是否为空 1.6:push_back与…...

#其它:面试题
第一面试官提问如下: 1、自我介绍 2、根据项目提问:混合开发调取api的通讯方式 3、技术提问:如何隐藏div,但是div需要存在 使用 visibility 隐藏: 1.visibility: hidden2.display: none 3.opcity: 04、css塌陷问题…...

计算机视觉中的双边滤波:经典案例与Python代码解析
🌟 计算机视觉中的双边滤波:经典案例与Python代码解析 🚀 Hey小伙伴们!今天我们要聊的是计算机视觉中的一个重要技术——双边滤波。双边滤波是一种非线性滤波方法,主要用于图像去噪和平滑,同时保留图像的边…...

【AI日记】24.11.17 看 GraphRAG 论文,了解月之暗面
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 核心工作 内容:看 GraphRAG 论文时间:4 小时评估:不错,继续 非核心工作 内容:了解国内大模型方向,重点了解了创业独角兽-月之暗面&…...

Front Panel Window Bounds 与 Front Panel Window Bounds 的区别与应用
在LabVIEW中,Front Panel Window Bounds 和 Front Panel WindowBounds 是两个不同的属性节点,用于描述前面板窗口的位置和大小。它们的区别主要体现在它们表示的是窗口的不同部分,具体如下: 1 Window Bounds:调整整个…...