一、题目分析
判断两个链表相交,就要找到两个相同的节点。
方法1:正常来说可能需要从一个链表list1中取出一个节点,将其与list2中的每一个节点进行比较。再去list1的下一个节点,进行比较。直到找到相同节点或遍历完全。时间复杂度O(N*N)。
方法2:计算出两个链表的长度,让较长的链表走到与较短链表的头节点的相同位置处。此时让两个节点同时走动,如果两个节点有相同的时候,那么两个链表相交。否则不相交。
如上图所示:第一个链表要比第二个链表长,便让head1从val=2的节点运动到val=4的节点。这样两个相同长度的链表便可以很轻松的找到相交的节点。只需要同时运动即可。
二、代码分析
1、链表长度
int ListLenth(ListNode* head)
{
int n=0;
while(head)//遍历链表求长度
{
n++;
head=head->next;
}
return n;
}
链表的长度一开始并不知道,所以要进行计算来判断哪个链表长度较大。让较大的链表进行移动,并且移动多少距离也需要计算。上面的函数便是求链表长度的函数。
2、距离移动
int lenth1=ListLenth(headA);//链表1长度
int lenth2=ListLenth(headB);//链表2长度
int ans=abs(lenth1-lenth2);//长度差
利用ListLenth函数分别计算出链表长度lenth1和lenth2。
ans是两个链表的长度差,保证为整数。也是较长链表要先走的距离。
ListNode* headlong=headA;//较长链表
ListNode* headshort=headB;//较短链表
if(lenth1<lenth2)
{
headlong=headB;
headshort=headA;
}
while(ans--)//移动较长链表
headlong=headlong->next;
在开始时假定headA是较长的链表,headB是较短的链表。如果headB较长的话,只需要交换一下即可。
接着让headlong走ans的距离,使得剩余链表长度相同。
3、找出相交节点
while(headlong&&headshort)
{
if(headlong==headshort)//判断是否相交
return headlong;
headlong=headlong->next;
headshort=headshort->next;
}
return NULL;
最后循环遍历即可,找到相同的节点直接返回;如果没有相交,while循环中就不会返回,在结束后返回NULL即可。
三、完整代码
typedef struct ListNode ListNode;
int ListLenth(ListNode* head)//计算链表长度
{
int n=0;
while(head)//遍历链表求长度
{
n++;
head=head->next;
}
return n;
}
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenth1=ListLenth(headA);//链表1长度
int lenth2=ListLenth(headB);//链表2长度
int ans=abs(lenth1-lenth2);//长度差
ListNode* headlong=headA;//较长链表
ListNode* headshort=headB;//较短链表
if(lenth1<lenth2)
{
headlong=headB;
headshort=headA;
}
while(ans--)//移动较长链表
headlong=headlong->next;
while(headlong&&headshort)
{
if(headlong==headshort)//判断是否相交
return headlong;
headlong=headlong->next;
headshort=headshort->next;
}
return NULL;
}