牛客网剑指Offer——链表中环的入口结点

题目描述

一个链表中包含环,请找出该链表的环的入口结点。

方法一:

对链表进行遍历,利用set等结构,将已经遍历过的节点存入set,每遍历一个节点,判断set中是否已经存在该节点,如果存在,那么说明链表存在环,且该节点就是入口节点,返回该节点;如果遍历到NULL,说明已经到了链表结尾,说明该链表不存在环,返回NULL。

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if( pHead == NULL || pHead->next == NULL )
            return NULL;
         
        unordered_set<ListNode*> s;
        ListNode* p = pHead;
        while( p )
        {
            if( s.find(p) != s.end() )
                return p;
            s.insert(p);
            p = p->next;
        }
        return NULL;
    }
};

方法二:

分为两步:判断是否存在环,找到环的入口节点

1、判断是否存在环:利用两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步,如果两个指针相遇,则存在环;如果两个指针中任意一个等于NULL,说明不存在环。可以将相遇时的指针返回,后面会用到。

2、找环的入口:

首先判断环中节点个数,利用前面找到的相遇时的节点,该节点一定是在环中的,可以从该节点出发,一边向前一边计数,再次回到该节点时,就可以得到环中节点个数n了。

建立两个指针p1和p2,令p1先走n不,然后p1和p2以相同速度向前移动,直到他们相遇,他们相遇的节点就是环的入口,如下图所示


代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if( pHead == NULL || pHead->next == NULL )
            return NULL;
         
        ListNode* meetingNode = MeetingNode(pHead);
        if( meetingNode == NULL )
            return NULL;
         
        ListNode* p = meetingNode->next;
        int count = 0;
        while( p != meetingNode )
        {
            count++;
            p = p->next;
        }
        p = pHead;
        for( int i=0;i<=count;i++ )
            p = p->next;
        ListNode* p2 = pHead;
        while( p != p2 )
        {
            p = p->next;
            p2 = p2->next;
        }
        return p;
    }
     
    ListNode* MeetingNode(ListNode* pHead)
    {
        ListNode* p1 = pHead->next;
        ListNode* p2 = pHead->next->next;
         
        while( p1 != NULL && p2 != NULL )
        {
            if( p1 == p2 )
                return p1;
            p1 = p1->next;
            p2 = p2->next;
            if( p2 != NULL )
                p2 = p2->next;
            else
                return NULL;
        }
        return NULL;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36132127/article/details/80168924