首先要判断一个链表是否是循环的,只要设置一个fast指针和slow指针,每次fast指针走两步,slow指针走一步,如果fast等于NULL证明不存在circle,如果fast==slow,则证明存在circle 然后假如链表存在循环要找出链表的入口的话,需要一点计算技巧,设起点到循环入口的距离为L,循环的长度为R。两个指针第一次相遇的位置为 x%R,x为slow指针在循环圈中走的距离,这时候有(2*(L+x)-L)%R=x%R,整理得有(L+x)%R==0 所以也就是说slow指针只需要在移动L步就可以到达循环的入口处,而这个时候我们需要将fast指针移到开头走L步,便有fast等于slow。所以我们只需要将fast移到开头后,然后每走一步判断fast和slow是否相等,如果相等,返回fast指针即可。注意的是L可能为0,所以我们需要将fast和slow先判断下,然后再进行各移动一步的操作。
代码如下
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution
{
public:
bool hasCycle(ListNode *head)
{
if(head == NULL)
return false;
ListNode *fast = head;
ListNode *slow = head;
while (true)
{
fast = fast->next;
if(fast == NULL)
return false;
if(fast == slow)
return true;
fast = fast->next;
if(fast == NULL)
return false;
if(fast == slow)
return true;
slow = slow->next;
}
}
ListNode *detectCycle(ListNode *head)
{
if(head == NULL)
return NULL;
ListNode *fast = head;
ListNode *slow = head;
while(true)
{
fast = fast->next;
if(fast == NULL)
return NULL;
fast = fast->next;
if(fast == NULL)
return NULL;
slow = slow->next;
if(fast == slow)
{
fast = head;
break;
}
}
while(true)
{
if(fast == slow)
return fast;
fast = fast->next;
slow = slow->next;
}
}
};