题目:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
Follow up: Can you solve it without using extra space?
解释:
判断是否有环的时候,用快慢指针做,快指针每次走两步,慢指针每次走一步,如果有环的话,慢指针指向交点,快指针返回到head
,快慢指针都以1的速度前进,那么两个指针再次相遇的时候,所在的位置就是环的入口:
证明:假设直链的长度为a
,快慢指针相遇时,距离环的入口的位置为b
(按照行走方向的距离),环的长度为x
,那么相遇的时候(快慢指针一定是在慢指针进入圈的第一圈相遇,可以推一下)
快指针距离入口结点的距离为:(2*slow-a)%x
慢指针距离入口结点的距离为:(slow-a)%x
而且slow=(a+b)
所以(a+2*b)%x=b%x
,根据同余定理得:(a+b)%x=0
,也就是a=n*x-b
,这个等式可以理解为,当一个指针走完a的长度,另外一个指针还差b的长度就走完了n倍的环。目前把fast指针放回head,每次指向它的next,让它走a的长度;slow指针位置不变还是在b,速度变为每次指向next。那么当fast走完了a的长度,slow应该刚好走完n倍的环,于是在起点相遇。
python代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
slow=head
fast=head
while fast and fast.next:
fast=fast.next.next
slow=slow.next
if fast==slow:
break
else:
return None
fast=head
while fast!=slow:
fast=fast.next
slow=slow.next
return slow
c++代码:
/**
* 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) {
ListNode* fast=head;
ListNode* slow=head;
while( fast &&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
break;
}
if (!fast ||!fast->next)
return NULL;
fast=head;
while(fast!=slow)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
};
总结:
同余定理:
(a−b)modK=0
->(amodK)=(bmodK)
python的while ...else
真的很神奇,而c++还需要判断一下结束循环的原因。