现在的位置: 首页 > 综合 > 正文

编程之美-3.6-编程判断两个链表是否相交

2013年05月18日 ⁄ 综合 ⁄ 共 1312字 ⁄ 字号 评论关闭

1. 简述

    给出两个链表的头指针,比如h1,h2,判断这两个链表是否相交。这里是为了简化问题,我们假设两个链表不带环。

    扩展:如果链表可能有环呢?

    扩展:如何求出两个相交链表的相交的第一个节点。

2. 分析

    这道题,个人感觉理解的还是相对比较清楚完整。主要就是两个问题,问题一,两个链表是否相交,问题二,两个链表如果相交,求得相交第一个节点。

    如果两个链表相交,那么要么两个链表都没有环,要么都有环。所以我们首先判断h1和h2是否有环:三种情况:一个有环一个没环(这种情况说明肯定不相交),两个都有环(需要进一步判断),两个都没有环(需要进一步判断)。

    一个链表是否有环的判断方法很简单,就是两个指针,一个一次走一步,另一个一次走两步,如果有环,那么两个指针早晚进入环,两个指针的相对速度正好是1,因此距离会一点一点减少,直到两个指针相遇,如果其中一个指针变为空了,说明不存在环。

    对于都没有环的两个链表:如果相交比如是从尾部向头部的若干个节点相交(至少1个),可以直接判断两个链表的最后一个节点地址是否相同。如果要寻找第一个相交的节点,也很容易,计算两个节点的长度差,假设为k,让较长的链表先走k步,然后,每走一步前先判断节点地址是否相等即可。

    对于都有环的两个链表:如果他们相交那么两个链表的环的部分必然是重合的,因为一个链表如果有环必然是形如数字6的情况。注意这里不能用两个指针分别从两个链表走,因为,如果链表相交,那么一快一慢的指针会相交,但是如果链表不相交,那么两个指针永远都不会相交,而且都在各自的环中不停的走,这样无法结束循环的。这里需要转换思路,首先求得链表进入环的第一个节点,因为这个节点也在环上,所以这个节点必然是相交的,只要判断这个节点地址是否相同即可。对于相交的第一个节点,其实如果找到两个链表进入环的第一个节点了,那么从头节点到这个节点,就转化为两个单链表的形式了,进入环的第一个节点相当于单链表的最后一个节点。

    关键在于寻找带环链表的进入环的那个节点。方法如下:两个指针,一个走一步,一个走两步,在环中相遇位置为X,然后从头节点和X位置,分别一步一步的走,每次判断是否相遇,相遇点就是所求节点。

    证明如下:假设头节点位置为A,第一个节点为M,相遇节点为X,环长为Len。

    因为快节点每次比慢节点快一步,慢节点进入后快节点不用一圈就能赶上慢节点了。

    慢节点走的路程 = AM + MX

    快节点走的路程 = AM + MX  + n * Len



    2*(AM + MX ) = AM + MX + n *Len (即: 2 * 慢节点走的路程 = 快节点走的路程

    AM + MX = n*Len

    AM = n*Len - MX

    AM = (n-1)*Len + (Len -MX)

    AM = (n-1)*Len + XM 就是这句话了,说明从A到M的距离与X到M的距离,同余环长。因此分别从A和X走,必然相交于X节点。

3. 参考

    编程之美,3.6节,编程判断两个链表是否相交

from: http://www.cnblogs.com/pangxiaodong/archive/2011/09/09/2172811.html

抱歉!评论已关闭.