若同时从一个环的某个点出发,fast指针每次走两步,slow指针每次走一步,则可证明slow指针走回起点时,fast指针也恰好到达起点。两种思路:一、fast指针每次比slow指针多走一步,fast指针想与slow指针同时到达某点,必须超过slow指针一圈,每次多走一步,假设环的节点数为N,则多走一圈需要走N次,此时slow指针恰好走完一圈指向出发点,fast指针亦然;二、fast指针的速度是slow的两倍,slow走k步,fast就走了2k步,fast指针要超过slow指针一圈即N步,即2k-k=N,一个很简单的方程,得k=N,所以slow指针走N步回到出发点时,fast和slow指针再次指向同一点。
那该怎么求解本题呢?设slow指针到达环的起始点要走k步,则fast指针此时已走了2k步,按照前述,fast指针想“赶上”slow指针需要走N-k次,此时fast和slow指针位于距环的起始点N-k步的位置,但N-k是指从起始点到这个点的步数,我们不能往回走,只能往前走,所有想再次回到起始点,必须再走N-(N-k)即k步。于是思路就很清晰了:先找出fast和slow指针“重合”即相等的地方,此时令slow = head,slow和fast每次只走一步,当走了k步(这个值不重要,只须判断fast和slow是否相等即可)fast和slow指针指向同一个节点使,这个节点即是环的起始点。若不存在这样的点,返回空指针。
/** * 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 *slow = head; ListNode *fast = head;
while(fast && fast->next)
{
slow = slow->next; fast = fast->next->next; if (slow == fast){ slow = head;
while (slow != fast)
{ slow = slow->next; fast = fast->next; }
return slow; } } return NULL; } };
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-06 22:53:24