題目描述
給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 。
爲了表示給定鏈表中的環,我們使用整數pos
來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果pos
是-1
,則在該鏈表中沒有環。
說明: 不允許修改給定的鏈表。
示例1:
輸入: head = [3,2,0,-4], pos = 1
輸出: tail connects to node index 1
解釋: 鏈表中有一個環,其尾部連接到第二個節點。
示例2:
輸入: head = [1,2], pos = 0
輸出: tail connects to node index 1
解釋: 鏈表中有一個環,其尾部連接到第一個節點。
示例3:
輸入: head = [1], pos = -1
輸出: no cycle
解釋: 鏈表中沒有環。
進階:
你是否可以不用額外空間解決此題?
我的思路
- 首先使用快慢指針(fast&slow)判斷鏈表是否有環
- 如果有環,如上圖。因爲使用了快慢指針,假設兩指針相遇於D點,因此fast比slow走的路程多一倍
- 則此時快指針走的路程爲
S1 = AB + BCDEB + BCD
(BCDEB表示一圈,字母順序表示方向) - 慢指針走的路程爲
S2 = AB + BCD
- 由於
S1 = 2 × S2
- =>
S1 = AB + BCDEB + BCD = 2 × (B + BD)
===(1) - =>
S2 = AB + BCD = BCDEB
===(2) - 證明了慢指針此時剛好走完全部路徑的一圈
- 題目要求輸出B點這一入環點,有
DEB = BCDEB - BCD
===(3)- 聯立(1)(2)(3),得出
AB = DEB
===(4)- 說明D到B的距離和A到B的距離相等
- 因此可以得出一種解決辦法:慢指針(或者快指針)從點D開始向前走DEB的距離,和一個新指針從A點開始走,兩個點會在B點相遇,這個B點就是我們需要的 入口點
代碼如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == NULL || head -> next == NULL){
return NULL;
}
bool hasCircle = false;
ListNode *fast = head;
ListNode *slow = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = last->next;
if(fast == slow){
hasCircle = true;
break;
}
}
if(hasCircle){---
L || head -> next == NULL){
return NULL;
}
bool hasCircle = false;
ListNode *fast = head;
ListNode *slow = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = last->next;
if(fast == slow){
hasCircle = true;
break;
}
}
if(hasCircle){
ListNode *temp = head;
while(temp != slow){
temp = temp->next;
slow = slow->next;
}
return temp;
}
else return NULL;
}
};