Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
解法思想:
算法思想就是设置一个快指针fp和一个慢指针sp,两个指针起始同时指向head节点,其中快指针每次走两步,慢指针每次走一步,那么如果链表有环的话他们一定能够相遇。可以想象两个人同时从操场上起跑,其中甲的速度是乙速度的2倍,那么当乙跑完一圈的时候甲也跑了两圈,他们一定能够相遇
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* pfast = head;
ListNode* pslow = head;
do{
if(pfast!=NULL)
pfast=pfast->next;
if(pfast!=NULL)
pfast=pfast->next;
if(pfast==NULL)
return false;
pslow = pslow->next;
}while(pfast != pslow);
return true;
}
};
为什么快指针一定要设置为慢指针的2倍
看了上面的题解也许你会问问什么快指针一定要设置为慢指针的2倍呢,为什么不是3倍。例如两个人同时从操场出发,其中甲的速度是乙的三倍,当乙跑完一圈的时候,甲跑了三圈,不也是可以相遇的吗。
接下来我会推导,设快指针fp的速度是慢指针速度sp的t倍,其他参数还和上面图片即解释一致。我们可以得出:
ts = s + nr
-> (t-1)s = nr (3)
由(2)和(3)可以得到:
(t-1)(a+x) = nr
-> (t-1)(a+x) = (n-1)r + r
-> (t-1)(a+x) = (n-1)r + (L-a)
-> a = (n-1)/(t-1)*r + [(L-a)/(t-1) - x]
其中a必定为整数,因为a代表的是h到d的结点个数。所以(n-1)/(t-1)和(L-a)/(t-1) 也须为整数,所以当t为2的时候,一定为整数,当然t也可以为其他,只是遇到链表不一样的情况时候所得到的a不一定为整数