两个链表的第一个公共结点
题目:输入两个链表,找出他们的第一个公共结点。
思路:
1、首先当然会想到暴力法。两重遍历,对链表1 中每个元素都去遍历一下链表2 ,这样时间复杂度是O(m*n)。不太行
2、想到要从尾部开始找就好了,所以想到反转链表,将两个链表都反转一下,然后开始比较。这样时间复杂度是O(n)。但是改变了链表的结构。
3、最后是双指针的方法。开始想到要用双指针,但是没想好怎么用。后面看了一些参考,恍然大悟!!
具体思路:
定义一个指针指向链表1:p1, 再定义一个指针指向链表2:p2.
如果p1 != p2; 则两个指针同时向后遍历,需要能遍历到尾结点后面的空节点,当是空节点是,p1 指向链表2 的头结点。p2也是,遍历到空结点时,p2 = headA;
继续遍历,如果有公共结点,肯定会相遇,如果没有,会一起遍历到尾结点后的空结点处
链表节点定义:
struct ListNode{
int val;
ListNode* next;
ListNode(int x): val(x),next(NULL){}
};
核心代码:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
//考虑其中一个链表为空的情况
if(!headA || !headB) return NULL;
//下面的代码就能把头结点相等的情况包括进去
ListNode* pA = headA;
ListNode* pB = headB;
//遍历判断
while(pA != pB){
pA = pA != NULL ? pA->next : headB;
pB = pB != NULL ? pB->next : headA;
}
return pA;
}
现在解释一下为什么这样操作:
假如链表1 非公共部分的长度是a, 链表2非公共部分的长度是b, 公共部分的长度是c .
当pA 第二次走到公共结点处时走了 a+c+b 的长度。
同理
当pB 第二次走到公共结点处时走了 b+c +a的长度
显然 两者相等,所以如果有结点一定会相遇!