不容许修改链表结构。算法
时间复杂度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; } };