两个单链表相交的一系列问题

【题目】在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数,如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null即可。要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到O(N+M),额外空间复杂度请达到O(1)。

先查看结构是否有环,用hash_set实现,从头节点开始遍历链表,查到一个不在set中的节点就放到set中,查到一个在set中已经存在的节点,就说明该节点是第一个入环的节点,返回它,如果遇到空,就说明无环,返回null

那么不用哈希表怎么做呢

准备两个指针f、s。f一次走两步,s一次走一步,如果f遇到null了,说明必然无环,如果有环,f和s一定会在环上相遇,相遇的时刻,f回到开头,让f调整为一次走一步,s也走一步,它们两个一定会在第一个入环节点相遇,这是个玄学(结论啦,是个数学证明),记住就好。

现在解决了链表有无环的问题,就可以开始下一步了,
如果两个链表都无环,怎么找到第一个相交的节点呢?
两个单链表相交的一系列问题

简单一点还是先用hash_set,先把第一个链表放入map里,然后遍历链表2,找到的第一个在map里的节点,就是第一个相交的节点,如果遍历到空,说明不相交

那不用map怎么做呢,

先遍历链表1,统计链表1的长度,得到len1,以及链表1的最后一个节点end1,然后遍历链表2,得到len2和end2 ,然后判断年&end1是否等于&end2,如果&end1!=&end2,则这两个链表不可能相交,如果&end1==&end2,则相交,但未必是第一个相交的节点

接下来找第一个相交的节点

举个例子,如果len1=100,len2==80,哪个先链表1先走20步,然后链表2和链表1一起走,它两一定能一起走到第一个相交的点

这样就判断了,两个无环单链表是否相交的问题,

那么如果一个单链表有环,一个单链表无环,要怎么判断是否相交呢?

直接出结论,不可能相交,因为是单链表

那如果两个但链表都有环呢?

两个链表都有环,有三种拓扑结构
1、各自成环,两个没关系,不相交
2、两个链表先相交,然后共享一个环
两个单链表相交的一系列问题
3、两个单链表相交的一系列问题

现在只要找到loop1和loop2(第一个入环节点),就能区分开这几种情况,

如果&loop1==&loop2,就说明是第二种拓扑两个单链表相交的一系列问题

这种情况下,相当于是无环结构相交,上面已经探讨过了

如果loop1!=loop2,可能是拓扑1,也可能是拓扑3,

那么怎么区分这两种情况呢?

让loop1继续走,如果走到底了,还没遇到loop2,就应该是拓扑1,如果遇到了,就是拓扑3,那么这个相交节点,就是loop1或者loop2都对