題目: https://oj.leetcode.com/problems/linked-list-cycle-ii/指針
這一題的細節真是魔鬼。並且,好像沒什麼通常性,感受就是一個智力遊戲
首先, 設兩個指針, s(慢指針) 和 f(快指針), s每次走一步, f每次走2步.
剛開始的時候, s 和 f 都站在head, 誰先走呢? 應該是f先走. 並且 f每走完一步, 都要檢查一下腳下是否是NULL,是的話,就知道沒有環了, 直接退出.
好, 如今假設是有環的. 有環的話, 確定在某個時候, f會跟s重合. 可是, 問題是, 咱們要把這個"f和s是否是重合"的檢查,放在哪裏呢?
剛開始的時候, 我覺得放在哪裏都行, 若是這道題只是問你, 有沒有環, 其實放在哪裏都是能夠的.
可是問題是, 這道題還要求你把環的開始節點找出來, 問題就沒有那麼簡單了.
放在哪裏好呢? 既然是f先走,s後走,很天然,能夠定義一個"時間單位"的概念, 在一個"時間單位"了, f先走兩步,而後s走一步.
能夠考慮, 把這個檢查放在時間單位的後面, 也就是說, 你不能在時間單位的中間檢查, 爲何不能呢? 這個真的很難說...最好的辦法就是, 畫個圖, 我想了好久才發現, 因此說,這道題的細節真是魔鬼
假設某個時間單位後, s到達了環的開始節點, 這時候, f確定在環中的某個節點X.
假設從這個X出發, 再走k步, 就能夠到達環的開始節點. 那麼, 咱們能夠推斷, 再過k個時間單位, s 和 f 就會重合. (其實, 在某個時間單位的中間, s 和 f就已經重合了, 這就是爲何不能在時間單位的中間檢查)
假設, 如今s和f重合了. 這時候, 咱們再設一個指針m站在head. 而後, 神奇的事情就要發生了.
咱們從新定義一個時間單位爲"讓m走一步, s再走一步"
你會發現, 通過若干個時間單位之後, m和s就會重合, 並且重合的那一點, 竟然就是環的開始.
要說明爲何, 文字真的很吃力, 最好的辦法就是畫圖, 摸清楚各個階段裏面, 各個位置, 以及各個位置之間的距離關係code
如下是代碼:遊戲
/** * 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) return NULL; ListNode * s = head; ListNode * f = head; ListNode * m = head; while(1) { f=f->next; if (f == NULL) return NULL; f=f->next; if (f == NULL) return NULL; s=s->next; if (f == s) break; } while (1) { if (m == s) return m; m = m->next; s = s->next; } } };