160. Intersection of Two Linked Lists(easy)
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
begin to intersect at node c1.
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.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.
开始写题解的第二天,周日一大早就起来忙活,真是佩服自己的热情…希望能多坚持一会儿…
又拿了一道水题(误),仔细读了以后发现似乎并不水啊…题目要求找到两个无环链表的公共段的起始点(示意图已经很清楚了),如果没有公共段,则返回NULL。要求不能更改输入链表的结构,时间要求为O(n),空间要求O(1)。
分析一下,因为有可能并没有公共段,那至少两个链表都需要遍历一遍,时间O(n)也只能刚刚好是满足,空间O(1)加上不能更改链表,直接就堵死了统计的这条路,而且题目并没有说链表的val是唯一的,要判断公共点还是要靠地址…
唯一想到的就是之前判断链表是否有环的方法,利用一快一慢两个指针,可是这样时间复杂度有可能会退化到O(n^2),也没办法解决无公共端点的情况。面对一道easy尝试一个多小时都没有进展,心态炸了,手贱去看了discuss,以下就讲解以下其他人的方法吧:
根据题目已经,可以把链表分成3部分,A链独有部分(用A表示),B链独有部分(用B表示),公共的部分(用C表示)。解题的核心就是抓住一点:
A + C + B = B + C + A
同时用两个指针p1,p2,分别从链表A的头部和链表B的头部开始遍历。当p1遍历完链表A,到达尾部以后,接着从链表B头部开始遍历;p2同理,遍历完链表B以后从链表A头部开始遍历。可以证明在O(n)时间(只需要遍历一遍A+B)一定能够找到公共起始点。如果两个指针同时到达链表的尾部NULL,那么说明C为空集,没有公共部分。
代码:
class Solution{
public:
ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
ListNode* tmpA = headA;
ListNode* tmpB = headB;
while(1){
if (tmpA == NULL && tmpB == NULL) return NULL;
else if (tmpA == tmpB) return tmpA;
else if (tmpA == NULL){
tmpA = headB;
tmpB = tmpB->next;
}else if (tmpB == NULL){
tmpB = headA;
tmpA = tmpA -> next;
}else{
tmpA = tmpA -> next;
tmpB = tmpB -> next;
}
}
return NULL;
}
};
心态炸了心态炸了。