原题:
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.
如果两个链表有一个公共结点,那么 该公共结点之后的所有结点都是重合的(可参考原题中给出的“Y”形示意图),假设一个链表比另一个长X个结点,我们先在长的链表上先遍历X个结点,之后再同步遍历,这个时候就能保证同时到达最后一个结点了。由于两个链表从第一个公共结点考试到链表的尾结点,这一部分是重合的。因此,它们肯定也是同时到达第一公共结点的。于是在遍历中,第一个相同的结点就是第一个公共的结点。
我们可以先分别遍历两个链表得到它们的长度,并求出两个长度之差X。在长的链表上先走X步后,再同步遍历两个链表,直到找到相同的结点,或者一直到链表结束。此时,如果第一个链表的长度为m,第二个链表的长度为n,该方法的时间复杂度为O(m+n),空间复杂度为O(1)。
代码(C++):
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB)
{
if(headA==NULL||headB==NULL)
{
return NULL;
}
ListNode *pA = headA->next;
ListNode *pB = headB->next;
int lengthA = 0;
int lengthB = 0;
int temp = 0;
while(pA) //获取链表A长度
{
pA = pA->next;
lengthA++;
}
while(pB) //获取链表B长度
{
pB = pB->next;
lengthB++;
}
pA = headA;
pB = headB;
if(lengthA>lengthB)<span style="white-space:pre"> </span>//将两个链表对齐,长的链表先移动temp步
{
temp = lengthA-lengthB;
while(temp>0)
{
pA = pA->next;
temp--;
}
}
else
{
temp = lengthB-lengthA;
while(temp>0)
{
pB = pB->next;
temp--;
}
}
while(pA!=NULL)<span style="white-space:pre"> </span>//对齐后开始同步遍历
{
if(pA==pB)
{
return pA;
}
pA = pA->next;
pB = pB->next;
}
return NULL;
}
};