两链表相交问题

两单向链表相交问题

一、问题分析

(1)两个链表相交,那么两个链表中的节点一定有相同地址。

(2)两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。
(问:为什么? 答:因为每一个节点最多只能有一个下一节点,因此在相交节点之后,链表不可能再分为两个链表)

二、问题解法

根据两个链表是否存在环来分类讨论

1、无环

无环的情况有两种比较快速的解决方式,这两种方式本质上都是基于 一、问题分析 中的第二要素
① 制造环法

两链表相交问题

如果两链表相交,只会有上面这种情况(两链表合为一个链表),如果还有其他的情况,请拍砖

那么何为制造环法呢,依然看图
两链表相交问题

首先遍历链表A,遍历到A的尾节点时,将A的尾节点的下一节点设置为链表B的头结点。这样就会出现两种情况:
无环:(分析)因为两链表不存在交点,将A的尾节点的下一节点设置为链表B的头结点后,这两个链表就成为了一个无环链表
有环:(分析)因为两链表存在交点,因此在将A的尾节点的下一节点设置为链表B的头结点后,从相交点开始,原来的链表B就构成了一个环(本质:如果两链表存在交点,则尾结点一定相同。因此链表A的尾结点也就是链表B的尾结点,将链表A尾结点的下一节点设置为链表B的头结点就等价于将链表B的尾结点的下一节点设置为链表B的头结点,故一定会构成环

因此我们可以先将链表A的尾节点的下一节点设置为链表B的头节点。如果存在环,则AB链表存在交点;否则就是两条互不相干的链表(如何判断链表是否存在环,请参考我另外一篇博客。这篇只分析链表相交问题

那么问题来了,如何寻找相交点?其实很简单,仔细看看上图就很容易发现,这个环的入口结点就是两链表的相交点

② 比较尾节点法
相比上种方法,这种方法简直就是一点就通(之所以没放在第一个来讲是担心你们看了后就不认真看第二个,别打我~)

两链表相交问题

还是这张图,还是基于 一、问题分析 中的第二要素。
聪明的人肯定已经知道我接下来要说什么了,那么帅气的人就仔细听好

直接比较AB链表的尾结点是否相等即可
直接比较AB链表的尾结点是否相等即可
直接比较AB链表的尾结点是否相等即可

相等则表示有交点,不相等则表示没有交点。

那么问题又来了,这种方式又应该怎么寻找相交节点呢?
先遍历链表A得出链表A的长度S1
在遍历链表B得出链表B的长度S2
比较,选择长的那个链表(这里假设是链表A长)

先让链表A走S1-S2个节点(每次走一个节点,在链表B开始走之后也接着走);然后链表B也开始走,链表B每遍历一个节点都和链表A当前的结点比较。第一个相等的节点就是交点

2、有环

有环的话一般是两个链表都存在环
因为如果一个链表存在环而另外一个链表不存在环那么这两个链表肯定不存在交点(问:为什么?答:自己画图感受一下就会意识到这个问题有多么的愚蠢,当然如果你真的证明了存在这种情况。那么恭喜你肯定会在学术界引起轰动 )

而且如果两个链表都有环,如果它们有交点的话。那么它们一定共用一个环。如图下两链表相交问题
两个链表一定是在环的某个地方进入这个环,如果还有其他情况,欢迎拍砖(博主头铁2333)

现在,我们可以采用快慢指针来判断两个有环的链表是否存在交点。因为这个环是两个链表共用的,所以只要两个链表使用快慢指针,就一定会发生指针碰撞。

何为快慢指针,这里简单的提及一下。就是放两个指针,一个指针一次走两个节点(也可以走3、4甚至N个),一个节点一次走一个节点。这样只要存在环,那么两个节点就一定会相遇(其实一开始我也怀疑会不会走得快的那个节点会不好刚好跳过走得慢的那个节点,不过仔细画画图即可知道,一定会相遇。就像博尔特和宋小宝在一个环里面跑步,他们一定就相遇多次;反之,如果不存在环,则他们永远也不会相遇)

在链表A中放快指针,在链表B中放慢指针(反之也可以),然后每次遍历都判断两节点是否相等,只要相等就一定存在交点

那么问题又来了?如何寻找相交点?
这个问题博主还在思考,如果入口点不同的话,那应该是不存在交点吧….

欢迎拍砖和参与讨论~