题目
题目链接:142. 环形链表 II
思路–快慢指针
首先先判断是否有环:判断是否有环的思路就是快慢指针的方式;当快慢指针相遇时候一定有环!
其次,让慢指针从头结点开始走,而让相遇结点的指针从相遇点走;
当慢指针和相遇指针相等表示找到环的入口点;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode * slow = head;
struct ListNode* fast = head;
//先确认有环
//再找入环口点
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//相遇,即有环
if( fast == slow)
{
//meetNode 表示相遇结点
struct ListNode* meetNode = fast;
slow = head;
//开始找环入口点
while(meetNode != slow)
{
slow = slow->next;
meetNode = meetNode->next;
}
//找到返回任意一个meetNode 或者 slow
return slow;
}
}
//退出循环表示每找到环
return NULL;
}
证明从相遇点指针和头指针一起走,一定是环的入口
L
:head头结点到环的入口距离;
X
:环入口到相遇点的距离;
C
:环的距离大小;
C-X
:相遇点到环入口的距离;
当slow 和 fast 相遇的时候 :
slow
走过的距离是L + X
;
fast
走过的距离是L+X + N*C
;其中N表示环的圈数;
当 fast 走的步数是慢指针的两倍时候:
那么就有一个关系:2(L+X) = L+X +N*C
;
化简有:L = N*C - X
; 表示head头结点到环的入口距离 = 圈数的距离 — 环入口到相遇点的距离;
即为 相遇点到环的距离:C - X
,因为N只是圈数的关系,没有实际的算术关系!
那么就证明了 L = C - X
;
即证明从相遇点指针和头指针一起走,一定是环的入口!前提是因为我们假设了L的距离就是到环的入口!!!!