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中的每一节点,在链表B中都遍历一遍,算法复杂度为O(m*n),代码如下:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *ret = nullptr;
if(!headA || !headB)
return ret;
ListNode *p_a = headA;
while(p_a)
{
ListNode *p_b = headB;
while(p_b)
{
if(p_a == p_b)
{
ret = p_a;
return ret;
}
p_b = p_b->next;
}
p_a = p_a->next;
}
return ret;
}
对于一个有追求的刷题者,这种解法显然是不合适的。在剑指offer中,分析了几种思路,一种是借助辅助栈来保存所有链表节点,然后根据出栈时进行判断,时间复杂度和空间复杂度都是O(m + n)。我们对链表进行深入分析后可以发现,若有相同节点,则以后的节点都相同,因此可先计算出链表的长度,让较长的那个链表先走长度差步,这样判断以后的节点,即可找出相同的节点,代码如下:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unsigned int len1 = getListLength(headA);
unsigned int len2 = getListLength(headB);
int len_diff = len1 - len2;
ListNode *p_a = headA, *p_b = headB;
if(len_diff > 0)
{
while(len_diff-- > 0)
{
p_a = p_a->next;
}
}
else
{
while(len_diff++ < 0)
{
p_b = p_b->next;
}
}
while(p_a && p_b)
{
if(p_a == p_b)
return p_a;
else
{
p_a = p_a->next;
p_b = p_b->next;
}
}
return nullptr;
}
unsigned int getListLength(ListNode *head)
{
unsigned int ret = 0;
ListNode *p = head;
while(p)
{
++ret;
p = p->next;
}
return ret;
}