题目
给定两个单链表的头节点head1和head2,单链表可能有环,也可能无环。如何判断两个链表是否相交?相交的话返回相交的第一个节点,不想交的话返回NULL。
要求:如果链表1的长度为N,链表2的长度为M,时间复杂度O(N+M),额外空间复杂度O(1)。
分析:
- 首先我们先判定两个链表是否有环,如果只有其中一个链表有环,一个链表无环,那证明这两个链表不会相交。然后再分成都有环和无环情况分别分析。
- 都无环的情况:先求得每一链表的环的入口节点loop1和loop2。可参见
代码如下:
ListNode *getLoopNode(ListNode *head){
if(head==NULL||head->next==NULL||head->next->next==NULL){
return NULL;
}
ListNode *pSlow=head->next;
ListNode *pFast=head->next->next;
while(pSlow!=pFast){
if(pFast->next==NULL||pFast->next->next==NULL){
return NULL;
}
pSlow=pSlow->next;
pFast=pFast->next->next;
}
pFast=head;
while(pSlow!=pFast){
pSlow=pSlow->next;
pFast=pFast->next;
}
return pSlow;
}
无环的情况有两种可能,分别如下:
这种情况的求解的基本思想如下:
先求出两个链表长度的差值n,让长链表先走n步,然后一起走,如果能相遇则证明两个链表有相交,反之则没有。
代码如下:
ListNode * noLoop(ListNode *head1,ListNode *head2){
if(head1==NULL||head2==NULL){
return NULL;
}
ListNode *cur1=head1;
ListNode *cur2=head2;
int n=0;
while(cur1->next!=NULL){
n++;
cur1=cur1->next;
}
while(cur2->next!=NULL){
n--;
cur2=cur2->next;
}
if(cur1!=cur2){//最后的节点不相同直接返回false;
return NULL;
}
cur1=n>0?head1:head2;
cur2=cur1==head1?head2:head1;
n=abs(n);
while(n!=0){
n--;
cur1=cur1->next;
}
while(cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}
- 都有环的情况下:有如下三种可能
- case 1和case 2其实可以合并在一起处理,也就是说他们的入环节点loop1跟loop2是不相同的,那么让一个节点从loop1或loop2开始走,走一圈过程当中如果节点遇到loop2或loop1,则证明两链表是相交的,如果走了一圈没有相遇,则证明两链表是不相交的。
- case 3类似于无环情况,基本思想都是先让长链表先走两链表的差值步(这里差值步为两链表未到入环节点的差值),然后两链表一起走,如果相遇,证明相交。
代码如下:
LisNode * bothLoop(ListNode *head1,ListNode *loop1,ListNode *head2,ListNode *loop2){
ListNode *cur1=NULL;
ListNode *cur2=NULL;
if(loop1==loop2){
cur1=head1;
cur2=head2;
int n=0;
while(cur1!=loop1){
n++;
cur1=cur1->next;
}
while(cur2!=loop2){
n--;
cur2=cur2->next;
}
cur1=n>0?head1:head2;
cur2=cur1==head1?head2:head1;
n=abs(n);
while(n!=0){
n--;
cur1=cur1->next;
}
while(cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}else {
cur1=loop1->next;
while(cur1!=loop1){
if(cur1==loop2){
return loop1;
}
cur1=cur1->next;
}
return NULL;
}
}
总体测试代码如下:
#include <iostream>
#include <math.h>
using namespace std;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int data):val(data),next(NULL){}
};
ListNode *getLoopNode(ListNode *);
ListNode *noLoop(ListNode *,ListNode *);
ListNode *bothLoop(ListNode *,ListNode*,ListNode *,ListNode*);
ListNode *chkInter(ListNode* head1, ListNode* head2) {
// write code here
if(head1==NULL||head2==NULL)
return NULL;
ListNode *loop1=getLoopNode(head1);
ListNode *loop2=getLoopNode(head2);
if(loop1==NULL&&loop2==NULL){
return noLoop(head1,head2);
}
if(loop1!=NULL&&loop2!=NULL){
return bothLoop(head1,loop1,head2,loop2);
}
return NULL;
}
int main()
{
// 1->2->3->4->5->6->7->null
ListNode *head1=new ListNode(1);
head1->next=new ListNode(2);
head1->next->next=new ListNode(3);
head1->next->next->next=new ListNode(4);
head1->next->next->next->next=new ListNode(5);
head1->next->next->next->next->next=new ListNode(6);
head1->next->next->next->next->next->next=new ListNode(7);
//0->9->8->6->7->null
ListNode *head2=new ListNode(0);
head2->next=new ListNode(9);
head2->next->next=new ListNode(8);
head2->next->next->next=head1->next->next->next->next->next;
cout<<chkInter(head1,head2)->val<<endl;
}
ListNode *getLoopNode(ListNode *head){
if(head==NULL||head->next==NULL||head->next->next==NULL){
return NULL;
}
ListNode *pSlow=head->next;
ListNode *pFast=head->next->next;
while(pSlow!=pFast){
if(pFast->next==NULL||pFast->next->next==NULL){
return NULL;
}
pSlow=pSlow->next;
pFast=pFast->next->next;
}
pFast=head;
while(pSlow!=pFast){
pSlow=pSlow->next;
pFast=pFast->next;
}
return pSlow;
}
ListNode * noLoop(ListNode *head1,ListNode *head2){
if(head1==NULL||head2==NULL){
return NULL;
}
ListNode *cur1=head1;
ListNode *cur2=head2;
int n=0;
while(cur1->next!=NULL){
n++;
cur1=cur1->next;
}
while(cur2->next!=NULL){
n--;
cur2=cur2->next;
}
if(cur1!=cur2){//最后的节点不相同直接返回false;
return NULL;
}
cur1=n>0?head1:head2;
cur2=cur1==head1?head2:head1;
n=abs(n);
while(n!=0){
n--;
cur1=cur1->next;
}
while(cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}
ListNode* bothLoop(ListNode *head1,ListNode *loop1,ListNode *head2,ListNode *loop2){
ListNode *cur1=NULL;
ListNode *cur2=NULL;
if(loop1==loop2){
cur1=head1;
cur2=head2;
int n=0;
while(cur1!=loop1){
n++;
cur1=cur1->next;
}
while(cur2!=loop2){
n--;
cur2=cur2->next;
}
cur1=n>0?head1:head2;
cur2=cur1==head1?head2:head1;
n=abs(n);
while(n!=0){
n--;
cur1=cur1->next;
}
while(cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}else {
cur1=loop1->next;
while(cur1!=loop1){
if(cur1==loop2){
return loop1;
}
cur1=cur1->next;
}
return NULL;
}
}
输出: