题目
Write a program to find the node at which the intersection of two singly linked lists begins.
Notes:
- If the two linked lists have no intersection at all, return null.
- The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
解法一
思路
由于两个链表在尾部可能存在相同的部分,如果将其中一条链表的尾部连到另一条链表的头部,那么就可以构造一个环。题目就转化为求环的入口结点。下面先对环的几个概念作出分析。
单链表是否存在环?
解答这个问题,只需要设置快慢指针即可。慢指针一次走一步,快指针一次走两步。如果存在环,那么快指针终会赶上慢指针。设想一下,假如快指针追到慢指针身后一步,那么慢指针走一步,快指针走两步后,下一次就会相遇。如果快指针落后慢指针两步或者三步,再多走一次或两次两者就会达到只差一步的情况。所以两个指针终将相遇。
求环的长度。
从快慢指针相遇结点开始,让一个指针每次走一步,那么下次回到这个结点所走过的路程,就是环的长度。
求存在环的单链表的环的入口结点。
设单链表头结点到入口结点的距离为a,入口结点到快慢指针相遇结点的距离为x,单链表总长度为L,环长为r。当快慢指针相遇时,设慢指针走的步数是s,则快指针走的步数是2s。
s = a + x;
2s = s + nr;
a + x = nr = (n-1)r + r = (n-1)r + L - a;
a = (n-1)r + L - a - x;
所以,设置两个指针,起点分别是链表头结点和快慢指针相遇结点,同时前进,每次走一步。那么总会相遇在入口结点处。
代码
|
|
这个解法实际上就是求存在环的单链表的环的入口结点。
解法二
这两个链表有一个特点,就是相同的地方必定在尾部。但是由于两条链表长度不一定相等,如果同时遍历的话,很难让相同的结点对齐。因此,这个解法用了一个小技巧,让两个链表在按顺序从头到尾遍历的时候,能够做到尾部对齐。
|
|
一开始仍然让两链表从头开始遍历,每次走一步。链表A遍历到末端回到链表B的头部,链表B遍历到末端也回到链表A的头部。这样当两个遍历指针都到达另一个链表的时候,恰好可以让尾部对齐,消除掉长度差的影响。