问题:如果单链表中存在环,求环的起始位置
解:在上篇文章中,利用追逐法判断一个单链表是否存在环。求环的起始位置,需要求解单链表的长度和环的长度的关系。如果确定了单链表的长度和环的长度的关系,那么环的起始位置就呼之欲出了。
在判断单链表中有两个指针P和q,p每次前进两步,q每次前进一步,p的速度是q的两倍。设单链表的长度为L,环的长度为R,链表起点到环起点的距离为X,当p和q相遇时,慢指针总共走了S步,在环内总共走了a步,快指针总共走了2S步,此时满足:2S=S+n*R,所以S=n*R。
S=X+a;
X+a=(n-1)*R+R=(n-1)*R+L-X
X=(n-1)*R+L-X-a
其中(n-1)*R+L-X表示相遇的位置,L-X表示环的长度,L-X-a表示相遇点到达环起始位置的距离。也就是说,链表起点到环起点的距离X等于从相遇位置到达环起点的距离。这一结论是解决这道题的理论基础。当快慢指针相遇后,让快指针p重新指向链表的起点位置,重新设置p的速度和q的速度相同,当p和q再次相遇时的位置就是环的起始位置。具体实现代码如下:
1 linkNode *circleStart(linkNode *head) 2 3 { 4 linkNode *p,*q; 5 p=q=head; 6 while(p!=null && p->next!=null) 7 { 8 p=p->next->next; 9 q=q->next; 10 if(p==q) 11 break; 12 } 13 if(p==q &&p!=null) 14 { 15 p=head; 16 while(p!=q) 17 { 18 p=p->next; 19 q=q->next; 20 } 21 return p; 22 } 23 else{ 24 return null; 25 } 26 }