連接:https://leetcode-cn.com/problems/linked-list-cycle-iinode
給定一個鏈表,返回鏈表開始入環的第一個節點。 若是鏈表無環,則返回 null。c++
爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。 若是 pos 是 -1,則在該鏈表中沒有環。函數
說明:不容許修改給定的鏈表。spa
示例 :指針
輸入:head = [3,2,0,-4], pos = 1
輸出:tail connects to node index 1
解釋:鏈表中有一個環,其尾部鏈接到第二個節點。code
這道題的解法十分巧妙,只能膜拜。。用到了快慢指針,讓快慢指針同時走,可是快指針一次走兩步,慢指針一次走一步。能夠想象,當慢指針走到出現環的交點時,快指針已經走到環中的某個位置了。假設慢指針走了x步到達交點,那麼快指針此時已經走了2x步。假設快指針還要走y步再次到達交點,那麼當慢指針從交點出發再走y步時,快慢指針相遇,這是由於快指針的速度是慢指針的2倍。當快慢指針相遇時,讓慢指針指向頭節點,快指針依然在相遇的位置,這時讓快慢指針都是一次走一步,那麼當快慢指針再次相遇的時候,就是所求的出現環的交點。這是由於,慢指針從頭節點走x步到達交點,和以前同樣。而快指針從相遇位置也是再走x步到達交點。blog
這道題畫個圖就很清楚,環的位置實際上是求快慢指針再次相遇時所在位置。索引
若是不存在環,那麼快慢指針不會走到環中去,因爲快指針走的快,因此它會一直走到空。當出現空的時候,說明不存在環,函數直接返回空就好。leetcode
c++代碼以下:io
1 class Solution { 2 public: 3 ListNode *detectCycle(ListNode *head) { 4 auto slow = head, fast = head; 5 while(fast){ 6 fast = fast->next; 7 slow = slow->next; 8 if(fast){ 9 fast = fast->next; 10 } 11 else break; 12 13 if(fast == slow){ 14 slow = head; 15 while(fast != slow){ 16 fast = fast->next; 17 slow = slow->next; 18 } 19 return slow; 20 } 21 } 22 return NULL; 23 } 24 };
在寫代碼的時候,出現了一個bug,看了很久纔看出來,錯誤代碼以下:
1 class Solution { 2 public: 3 ListNode *detectCycle(ListNode *head) { 4 auto slow = head, fast = head; 5 while(fast){ 6 if(slow != fast){ 7 slow = slow->next; 8 fast = fast->next; 9 if(fast){ 10 fast = fast->next; 11 } 12 else break; 13 } 14 else{ 15 slow = head; 16 while(slow != fast){ 17 slow = slow->next; 18 fast = fast->next; 19 } 20 return fast; 21 } 22 } 23 return NULL; 24 } 25 };
思路是同樣的,當快慢指針沒有相遇的時候,兩個指針以不一樣的速度向前走,直到相遇時讓慢指針回到頭節點再開始走,直到快慢節點在交點相遇。區別在於第二個代碼先判斷了快慢指針是否相遇,而在初始化時快慢指針都指向頭節點,因此第6行的判斷是不成立的,裏面的語句並無執行。仍是要多練習,才能避坑呀。