lintcode 带环链表2
描述
给定一个链表,如果链表中存在环,则返回到链表中环的起始节点,如果没有环,返回null。
样例
给出-21->10->4->5,返回10
解释:
最后一个节点5指向下标为1的节点,也就是10,所以环的入口为10
挑战
不使用额外的空间
思路
和带环链表找环一样,使用快慢指针,当fast == slow的时候,就说明有环了。此时通过数学计算可以证明此时slow指针走的步数等于环的长度。证明如下:
设slow指针走了i,则fast走了2i,再设环外长度为m,环长为n,则有如下的等式
(i-m)≡(2i-m)(mod n)
第一次相遇时(不包括第一次在head处)i-m=n-m,2i-m=2n-m,可以得到i = n.
也就是说,此时在环内已经走了n-m的长度,剩下m的长度。于是此时可以让slow从head处开始走,fast的步长变为1,再继续走,再次相遇时,就是环的入口。
代码
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The node where the cycle begins. if there is no cycle, return null
*/
ListNode * detectCycle(ListNode * head) {
// write your code here
if (!head || !head->next) return false;
ListNode *fast = head->next->next, *slow = head->next;
int index;
while (fast && fast->next) {
if (fast == slow) {
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
fast = fast->next->next;
slow = slow->next;
index++;
}
return NULL;
}
};