博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
判断两个链表是否相交并找出第一个相交节点
阅读量:4183 次
发布时间:2019-05-26

本文共 1681 字,大约阅读时间需要 5 分钟。

引言:链表问题是数据结构中的常见问题,对于面试、笔试都有很大的作用,那么如何判断两个链表是否相交并找出第一个相交节点?

分析:找出两个链表的交点首先就是判断链表是否相交,那么首先来看什么是两个链表相交?

一、什么是链表相交?

数据结构的链表定义中存储了指向下一个元素的指针,如果当两个链表有交点时,即两个链表会在各自链表中的某个结点,同时指向了相同的下一个结点,即如下图所示:

这里写图片描述
图中可以看出,从链表一和链表二的相交处开始,后续结点都为相同结点。

此外,还要记住以下几点:

①相交的两个单链表要么均有环,要么都没有环

②一个有环的单链表和一个无环的单链表不可能相交

二、怎么判断两个链表是否相交?

先判断两个单链表是否有环,若一个有环,一个无环,则肯定不相交,剩下的情况要么两个单链表都有环,要么都没有环。

两个单链表都为无环情况:

方法一:根据上图链表相交,可知,最简单的方法是判断两个链表的最后一个结点是否相等,如果相等,那么这两个链表就相交。时间复杂度为O(len1+len2)。

方法二:依次判断第一个链表中的每个节点是否在第二个链表中出现,若出现,则两个链表相交。时间复杂度为O(len1*len2),该时间复杂度比较大。

方法三:如下图所示

这里写图片描述

首先遍历第一个链表,找到它的尾部,并让它指向第二个链表的头部,然后两个链表就合二为一,成为了一个新的组合链表,现在只需要判断新的链表是否含有环即可。因为第二个链表头部在环上,所以从第二个链表开始遍历判断是否有环,可以减少时间复杂度,减少的为链表A的长度,最终时间复杂度为O(len1+len2)。

方法四:首先将第一个链表所有节点地址进行hash排序,并建立hash表,然后将第二个链表中每个节点地址进行判断,看是否在hash表中存在,弱国存在,则两个链表相交,时间复杂度为O(len1+len2)。

两个单链表都为有环情况(三种情况):

①第一个相交节点在环开始之前:

这里写图片描述
②第一个相交节点在环入口处:
这里写图片描述
③第一个相交节点在环内:
这里写图片描述
前两种相交的节点在环之前,和环开始的地方,对于他们来说第一次相交的节点是相同的。

但对于第三种情况,即相交在环内的情况来看,如图,对于链表一来说,P1点是第一次相交的节点,对于链表二来说P2点是第一次相交的节点。

判断相交方法:

方法一:将其中任意一个链表的环打破,即让尾节点指向null(记住保存原本应当指向的位置),然后判断第二个链表是否含有环,若第二个链表中无环,则两个链表相交,否则不相交(记住,两个链表本身就是有环的,一个有环的链表和一个无环的链表不存在相交点)。

这里写图片描述
方法二:利用判断单链表是否有环的方法,对链表一使用两个快慢指针进行判断是否有环,两个指针的碰撞点即在环上,那么判断链表二的环上是否包含该碰撞点就可以判断两个链表是否相交了。

三、怎么找到两个链表的第一个相交节点?

两个单链表都为无环情况:

方法一:依次判断第一个链表中的每个节点是否在第二个链表中出现,第一个出现在链表二中的节点即为第一个相交节点。

方法二:人为构造环,如下图

这里写图片描述
首先遍历第一个链表,找到它的尾部,并让它指向第二个链表的头部,然后两个链表就合二为一,成为了一个新的组合链表,找到新链表的环入口节点,即为两个链表相交的第一个节点。

方法三:分别遍历两个链表,记录链表长度len1,len2。用两个指针指向两个链表的头部,让长度较长的链表先走|len1-len2|步,然后两个指针共同走,当两个指针相等时,即为第一个相交链表。

两个单链表都为有环情况:

方法一:第一个相交节点在环之前和环入口节点的情况的方法,如上述方法三。

方法二:第一个相交节点在环内的情况方法如下,分别找到链表一和链表二的环入口节点,各自的环入口节点即为各自第一次相交的节点。即为下图中的P1和P2节点。

这里写图片描述

四、总结

如果两个单链表相交,那么一定是都有环或者都没有环,不存在一个有环一个没环的两个链表相交。所以,判断链表相交,首先判断两个链表是否有环。

根据有环和无环的情况,分别处理,判断出是否相交,进而找出第一个相交节点。

你可能感兴趣的文章
《tiny6410裸机程序》第六章:myled通过usb下载至nandflash不能运行
查看>>
《tiny6410裸机程序》第七章:S3C6410外部中断简介
查看>>
《tiny6410裸机程序》第八章:S3C6410外部中断控制寄存器
查看>>
《tiny6410裸机程序》第八章:S3C6410总中断控制寄存器
查看>>
《tiny6410裸机程序》第九章:tiny6410按键控制蜂鸣器程序
查看>>
有关free()函数的一个问题
查看>>
《Android系统学习》之bug定位
查看>>
《Linux内核编程》第七章:USB CORE与USB键鼠驱动
查看>>
《Android系统学习》之JAVA与C混合编程——JNI
查看>>
《C预处理》之#ifndef
查看>>
《Linux内核编程》第十三章:Linux对进程内存的二级页式管理
查看>>
ARM协处理器
查看>>
《miniOS分析》前言
查看>>
《Linux内核编程》第十四章:Linux驱动基础
查看>>
Linux平台下ARM-Linux交叉编译工具链
查看>>
Window平台下ADS自带ARMCC编译工具链
查看>>
micro2440/tiny6410使用JLINK直接烧录nand flash
查看>>
C编译器、连接器与可执行机器码文件
查看>>
android linker 浅析
查看>>
802.11 traffic id
查看>>