不容許修改鏈表結構。算法
時間複雜度O(n),空間複雜度O(1)。spa
若是鏈表有環,那麼在遍歷鏈表時則會陷入死循環,利用這個特徵,咱們能夠設計這樣的算法。設計
使用一個slow指針,一個fast指針。指針
slow指針一次日後遍歷以1個節點,fast指針一次日後遍歷2個節點,一直作這樣的操做。code
若是fast指針在遍歷過程當中,遍歷到了NULL節點說明鏈表沒有環。ip
不然當slow指針和falst指針相同,則說明環有節點。leetcode
咱們假定鏈表頭到環入口的距離是len,環入口到slow和fast交匯點的距離爲x,環的長度爲R。slow和fast第一次交匯時,設slow走的長度爲:d = len + x,而fast走的長度爲:2d = len + nR + x,(n >= 1),從而咱們能夠得知:2len + 2x = len + nR + x,即len = nR - x,(n >= 1),因而咱們能夠獲得這樣的算法。rem
使用一個cur指針指向鏈表頭節點,一個inter指針指向第一次的交匯點。get
cur指針和inter指針一塊兒日後遍歷。it
cur指針和inter指針相等時,cur和inter指針指向的就是環的入口節點。
inter指針在遍歷過程當中可能屢次(n >= 1)通過環入口節點,但當cur指針第一次達到入口節點時,inter指針此時必然也指向入口節點。
/** * 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 (NULL == head) return NULL; ListNode * fast = head; ListNode * slow = head; while (1) { fast = fast->next ? fast->next : NULL; if (NULL == fast) break; fast = fast->next ? fast->next : NULL; if (NULL == fast) break; slow = slow->next; if (slow == fast) break; } if (NULL == fast) return NULL; ListNode * cur = head; ListNode * inter = slow; while (cur != inter) { cur = cur->next; inter = inter->next; } return cur; } };