请写一个程序,找到两个单链表最开始的交叉节点。
注意事项
- 如果两个链表没有交叉,返回
null
。 - 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
下列两个链表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在节点 c1 开始交叉。
这里主要有两个思路:
方法一:
对于仅判断相交不相交的话:判断最后一个节点是否相同的办法并不慢,如果两个链表长度m,n 那么复杂度O(m+n),这是最优的复杂度
如何寻找交叉节点:指针p、q分别遍历链表a、b,假设q先到达NULL(即 假设a 比 b 长),此时从a的头发出一个指针t,当p到达NULL时,从b的头发出s,当s==t的时候即交点.
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
/**
* @param headA: the first list
* @param headB: the second list
* @return: a ListNode
*/
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// write your code here
ListNode *a = headA,*b = headB;
if(a == NULL || b == NULL)return NULL;
while(a->next !=NULL)a = a->next;
while(b->next !=NULL)b = b->next;
if(a!=b)return NULL;
a = headA;
b = headB;
while(a!=NULL && b!=NULL){
a = a->next;
b = b->next;
}
ListNode *c = NULL;
if(!a){
c = headB;
a = headA;
while(b != NULL){
b = b->next;
c = c->next;
}
while(1){
if(c == a)return a;
c = c->next;
a = a->next;
}
}
else{
c = headA;
b = headB;
while(a != NULL){
a = a->next;
c = c->next;
}
while(1){
if(c == b)return b;
c = c->next;
b = b->next;
}
}
}
};
方法二:可以将一个链表的尾节点指向另一个链表的头结点。如果交叉,那么这就形成了环,剩下的问题就是如何判断一个链表是否是环,同时要知道环的起始节点。