http://blog.163.com/song_0803/blog/static/4609759720120910373784/

这里是网上找到的一个分析的比较全面的文章。

想到这个问题是因为一场笔试,题目类似,笔试完,感觉做的不够理想。

一.无环的两个链表相交:(大家就不要想尾部是否分叉了,这个肯定是单链表,只有一个next指针,所以不会分叉)

按照原博主的想法:

1.直接法:就是把每个M和每个N链表比较,这样的复杂度O(M*N)

2.hash表:把M链表中每个元素的地址散列到hash表中,在寻找N中地址hash是否有一样的,我们都知道,hash表的查找效率是O(1),这样整体的时间复杂度就是O(M+N)//(Hash函数可以优化:由于节点地址指针就是一个整型,假设链表都是在堆中动态创建的,可以使用堆的起始地址作为偏移量,以地址减去这个偏移量作为Hash函数)

3.先跳过原博主的第三个方法,因为我认为这个是最好的,比Hash表还要好,因为Hash表多占了内存。

 第四个方法:两个链表有长有短,先知道他们的长度,让长的链表,先跳MAX(M,N)-MIN(M,N)个距离,这样后面它们的”起点“就是一样的了,然后他们同时前进,并比较,若相同,肯定是相交的那个点。

4.原博主的第三个方法:

也说明一下,三四方法原理其实是一样的,就是:两个链表相交的话,肯定最后一个点是一样的,那从后数,相交点肯定距离最后点也是一样的,这就是上个方法的思路。但是你不觉得奇怪?为什么不直接比较最后一个点呢?对,直接比较最后一个点,这就是这第四个方法的思路。

现在来分析下:

4方法只需要M+N的移动,比较一次就可以了,不要知道MN的大小。

3方法需要计算MN的大小(这里我们可以认为,这个是事先知道的,不用求的,因为一般增删改后都是会更新结构离的lengh的),我们可能只需要M(不同部分长度)+N(不同部分长度)的移动,但是需要MAX(M(不同部分长度,N(不同部分长度))次比较,我们知道”比较“是比”赋值“耗时的【

比较耗时长
比较有一个读a和b值得过程,然后比较要建立一个新的区间存储比较结果,
而复制只是读取b的值,然后存储到a的位置,根本不需要读取a原来的值。

】所以4方法就比3方法好多了,当然如果相交点很近的话也不一定,但是谁又知道相交点在哪呢,所以还是,4的时间复杂度平均更低。

2方法是以前认为最好的,但是却不是这个问题的最优解,不仅要hash(M+N)次,还要比较M+N,显然不是最好的,还要占空间。

二.两个有环

首先,我不认可博主的方法:

1.链表中是否有环的判断:我觉得应该用:Hash来判断。

楼主的方法是个用数学来解决的,我觉得太浪费时间了,而且让方程来解的方法一般都不是方法(只是感觉),楼主能想到这个方法来解决也是让我很佩服,但觉得太繁琐了。

2.链表有环,判断环的入口点:

用哈希相遇的那个点就是入口点。

3.相交的判断:(相交肯定是共享结尾环的,当然可能入口不同)

(1)首先分别找出两个链表入环的第一个结点记为p1,p2
(2)如果p1==p2,说明两个链表在入环之前或入环的第一个结点相交;则此时可以转为两个链表均不带环相交的判断,把p1,p2当作最后的末尾结点
(3)如果p1!=p2,此时两个链表可能完全不相交;也可能两个链表完全共有同一个环(可能就是入环的点不同)。
  这时,我觉得是应该让p1向下走看是否有p2,没有肯定不相交,有肯定交。
三、当一个链表中有环,一个链表中没有环时,两个链表必不相交。
That's all.