Intersection of Two Linked Lists
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.
例如,下面的两个链表
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在 C1 处交叉。
说明:
如果两个链表没有交叉点,返回null。
函数返回时链表必须保持它们原来的结构。
假设链表中没有环。
要求时间复杂度为 O(n),空间复杂度为 O(1).
分析:
计算链表的长度 lenA 和 lenB,他们的差 |lenA-lenB| 即为交叉点前的长度差,同时记录最后一个节点,如果最后一个节点都不想等则无交叉点。若有,则先让长的链表移动|lenA-lenB|个节点,然后两个同时移动,在交叉点就会相遇。时间复杂度 O(m+n)。
实现 1:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA || !headB)
{
return NULL;
}
/* |LenA-LenB| 的差即为非公共部分的长度差。
*长的一个先移动 |LenA-LenB| 的位置,然后一起移动,交点处即可得
*/
ListNode *pA = headA, *pB = headB;
int lenA = 1, lenB = 1;
while(pA->next)//计算 A 的长度,并记录最后一个节点指针
{
++lenA;
pA = pA->next;
}
while(pB->next)//计算 B 的长度,并记录最后一个节点指针
{
++lenB;
pB = pB->next;
}
if(pA != pB)//最后一个节点都不重合,肯定无重合部分
{
return NULL;
}
if(lenA >= lenB)//A 长,则先移动 lenA-lenB 个节点
{
pA = headA;
pB = headB;
for(int i = 0; i < lenA-lenB; ++i)
{
pA = pA->next;
}
}
else //B 长,则先移动 lenB-lenA 个节点
{
pA = headA;
pB = headB;
for(int i = 0; i < lenB-lenA; ++i)
{
pB = pB->next;
}
}
while(pA != pB)//同时移动
{
pA = pA->next;
pB = pB->next;
}
return pA;
}
};
实现 2:
根据以上原理,维护两个分别指向两个链表的指针同时扫描比较,当第一次到达链表尾时,则将指针指向另一个链表的头部接着扫描,再次到达链表尾则停止扫描。两个指针都走了两个链表的长度,如有交叉点则会在扫描过程中相遇。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *pA = headA, *pB = headB;
int hasTravel = 0;
if(!headA || !headB)
{
return NULL;
}
while(1)
{
if(pA == pB)
{
return pA;
}
pA = pA->next;
pB = pB->next;
if(NULL == pA)
{
if(hasTravel)
{
break;
}
pA = headB;
hasTravel = 1; //已经经过一轮
}
if(NULL == pB)
{
pB = headA;
}
}
return NULL;
}