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.
这个题目没有能自己独立得到解法,在Discuss上得到一种解法:
- 获取两条链表的长度;
- 让两指针分别对齐到距离尾节点相同距离的节点;
- 一步一步往后移直到找到交汇点。
根据以上思路,我做了以下C++实现:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = 0, lenB = 0;
for (ListNode *curA = headA; curA != nullptr; curA = curA->next) ++lenA;
for (ListNode *curB = headB; curB != nullptr; curB = curB->next) ++lenB;
ListNode *curA = headA, *curB = headB;
while (lenA > lenB) {
curA = curA->next;
--lenA;
}
while (lenB > lenA) {
curB = curB->next;
--lenB;
}
while (curA != curB) {
curA = curA->next;
curB = curB->next;
}
return curA;
}
然后我在Solution上看到一种更独特的解法:
- 指针pA、pB分别指向链表A、B的头结点,每次后移一个节点;
- 当pA到达A的尾节点,将pA重置为B的头节点;同样,当pB到达B的尾节点,将pB重置为A的头结点;
- 两指针继续后移,如果两者相遇,那么相遇点即是两链表的交汇点。
至于为什么上述方法可以生效,我想可以这么理解:不失一般性地,可以假设A链表短于B链表,那么pA先指向A得尾节点,被重置为B的头结点,那么当pB被重置时,走过的总步数为B链表的长度,那么此时两指针分别距离两链表的尾节点的距离是一样的,所以在往后移的过程中,如果两链表存在交汇点,那么两指针必然同时到达交汇点,如果不存在,那么两指针也是同时到达尾节点。
根据以上思路,我做了如下C++实现:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pA = headA, *pB = headB;
int flag = 2;
while (flag) {
if (!pA) {
pA = headB;
--flag;
}
else pA = pA->next;
if (!pB) {
pB = headA;
--flag;
}
else pB = pB->next;
}
while (pA != pB) {
pA = pA->next;
pB = pB->next;
}
return pA;
}