判断链表中是否有环存在:
设置两个指针p,q,开始时两个指针均指向head;
p每次向前移动一步,q每次移动两步;不断移动,若在移动过程中p和q重合(p == q)则说明有环(证明略)。
若链表中有环存在,则从head处到上述p和q指针初次相遇处的节点(由p和q指向)的距离(节点数),等于环的长度(节点数)。所有找到上述p和q初次相遇的节点后,分别从head和此节点开始,每次向前一步,再一次相遇的节点便是环的入口节点(证明略)。
设置两个指针p,q,开始时两个指针均指向head;
p每次向前移动一步,q每次移动两步;不断移动,若在移动过程中p和q重合(p == q)则说明有环(证明略)。
代码:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x):val(x), next(NULL)
{}
};
bool hasCircle(ListNode *head)
{
if(head == NULL)
return false;
ListNode *p = head;
ListNode *q = head;
while(q != NULL && q->next != NULL)
{
p = p->next;
q = q->next->next;
if(p == q)
return true;
if(p == NULL || q == NULL || q->next == NULL)
return false;
}
return false;
}
若链表中有环存在,则从head处到上述p和q指针初次相遇处的节点(由p和q指向)的距离(节点数),等于环的长度(节点数)。所有找到上述p和q初次相遇的节点后,分别从head和此节点开始,每次向前一步,再一次相遇的节点便是环的入口节点(证明略)。
代码:
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL)
return NULL;
ListNode *p = pHead;
ListNode *q = pHead;
while(p!=NULL && q != NULL && q->next == NULL)
{
p = p->next;
if(q == NULL || q->next == NULL)
return NULL; //无环
else
q = q->next->next;
if(p == q)
{
break;
}
}
q = pHead;
while(1)
{
if(p == q)
return p;
p = p->next;
q = q->next;
}
return p;
}
};