判断链表是否有环及找到环的入口节点

判断链表中是否有环存在:
设置两个指针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; 
    } 
};


posted @ 2015-08-22 23:33  sunp823  阅读(249)  评论(0编辑  收藏  举报