关于单链表的几个问题

时间:2021-02-14 20:05:20

Q:如何判断一个单链表是否有环,如果有环,找出环的入口点?


A:首先我们判断链表是否有环,设置两个指针slow和fast,指向单链表的头部,每个循环slow走一步,fast走两步。如果没有环,fast或者fast的next会走到NULL,否则fast在环里循环最终会和slow相遇,此时即存在环。

再看第二个问题,当slow和fast相遇时,假设fast已经在环内循环n圈,环长为r,同时fast走的长度为slow走的长度的两倍,设slow走了s步,则有

2*s=s+n*r => s=n*r,再设单链表头部到环入口的距离为a,环入口到相遇点得距离为x,则a+x=s=n*r,因此从单链表头部到相遇点的距离为环长的整数倍,因此我们可以将slow或fast指向单链表头部,和另外一个指针每次一步往前走,则再次相遇时他们同时指向的就是环的入口点。


 1 struct Node
 2 {
 3     int value;
 4     Node* next;
 5 };
 6 
 7 
 8 Node* FindLoopEntrance(Node* head)
 9 {
10     Node *slow,*fast;
11     slow=head;
12     fast=head;
13     while(fast && fast->next)
14     {
15         slow=slow->next;
16         fast=fast->next->next;
17         if(slow==fast)
18             break;
19     }
20 
21     //无环
22     if(!fast || !fast->next)
23         return NULL;
24 
25     slow=head;
26     while(slow!=fast)
27     {
28         slow=slow->next;
29         fast=fast->next;
30     }
31     return slow;
32 }

 

 

Q:找出两个单链表的第一个公共结点。


A:

方法1:将第一个单链表首尾连接,判断第二个单链表有没有环,如果有则说明两个单链表相交,此时可以求出第二个单链表的环入口结点,即为第一个公共结点。

方法2:如果两个单链表相交,则他们从第一个公共结点到最后一个结点肯定都相同,此时求出两个单链表的长度lenA和lenB,假设lenA>lenB,则将指向A链表头的指针先前进(lenA-lenB)步,而指向B链表的指针此时还指向B链表头,然后再将两个链表每次各走一步,则相遇就在第一个公共结点。