思路(證明有環):
定義快慢指針fast和slow,fast每次前進兩步,slow每次前進一步;
當fast和slow在到達鏈尾之前相遇的話,就證明有環(類似於在操場上跑步跑的慢的被快的套圈但總會遇到);
思路(找環結點):
fast和slow相遇之后,fast不動,slow回到最初的起點,然后一步一步的等在再次相遇,這時候相遇地點就是環結點
證明如下,是個數學問題。。。
設一環的距離是R,k代表環數
slow走過的距離:AB+BC
fast走過的距離:AB+BC+k*R
因為slow每次一步,fast每次兩步,所以距離有兩倍關系
2(AB+BC)=AB+BC+k*R
AB+BC=(k-1)*R+BC+CB
AB=(k-1)*R+CB
所以結論就是fast從C->B加k圈停在B的時候,slow正好從A->B到達B
1 #include <iostream> 2 using namespace std; 3 4 typedef struct ListNode* List; 5 struct ListNode { 6 int data; 7 List next; 8 }; 9 10 List judge(List L) { 11 if (L == NULL || L->next == NULL) 12 return NULL; 13 List fast = L;//定義快指針 14 List slow = L;//定義慢指針 15 while (fast->next->next != NULL &&fast->next!=NULL) { 16 fast = fast->next->next; 17 slow = slow->next; 18 //如果指針相遇跳出循環 19 if (fast == slow) 20 break; 21 } 22 //如果到頭也沒有找到證明沒有環 23 if (fast->next == NULL || fast->next->next == NULL) 24 return NULL; 25 26 //此時fast記錄相遇點,slow回到頭指針 27 slow = L; 28 while (fast != slow) { 29 fast = fast->next; 30 slow = slow->next; 31 } 32 //再次相遇的結點就是環結點 33 return slow; 34 }
思路參考https://segmentfault.com/a/1190000015308120