【剑指Offer-代码的鲁棒性】编程题23:链表中环的入口节点

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路1

首先要判断链表中有没有环:可以利用两个指针,初始都在head,一个指针移动的比较快(一次移动两个节点),另一个指针移动的比较慢(一次移动一个节点),如果两个节点最终相遇了,则说明链表中存在环;如果快指针的下一个节点为nullptr,则说明链表无环。如果链表有环,则快指针和慢指针相遇的节点一定在环中,从相遇节点移动n次可以再次到达相遇节点,则n就是环的长度。此时,再设置两个指针p1和p2,将指针p1先移动n步,然后再同时移动p1,p2,则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==nullptr)
            return nullptr;
        
        ListNode* meetingNode = getMeetingNode(pHead);
        if(meetingNode==nullptr)
            return nullptr;
        int nodeNumsInLoop = 1;    //环中的节点个数
        ListNode* temp = meetingNode->next;
        while(temp!=meetingNode)
        {
            temp = temp->next;
            nodeNumsInLoop++;
        }
        
        ListNode* pSlow = pHead;
        ListNode* pFast = pHead;
        for(int i=0; i<nodeNumsInLoop; i++)
            pFast = pFast->next;
        while(pSlow!=pFast)
        {
            pSlow = pSlow->next;
            pFast = pFast->next;
        }
        return pFast;
    }
    
    ListNode* getMeetingNode(ListNode* pHead)    //寻找环中的相遇点
    {
        ListNode* pFast = pHead;
        ListNode* pSlow = pHead;
        while(pFast->next!=nullptr)
        {
            if(pFast->next!=nullptr && pFast->next->next!=nullptr)
                pFast = pFast->next->next;
            if(pSlow->next!=nullptr)
                pSlow = pSlow->next;
            if(pSlow==pFast)
                return pFast;
        }
        return nullptr;
    }
};

思路2

首先判断环是否存在还是和思路 1 类似,使用快慢指针,慢指针每次走一步,快指针每次走两步,如果最终快慢指针相等,则说明有环。否则,如果快指针 fast->next==nullptr,则说明无环。若有环,则将慢指针 slow 回退到链表头,快指针位置不变,也就是相遇的位置,然后快慢指针每次都走一步,如果快慢指针相遇,则相遇点一定是入口。代码如下:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==nullptr) return nullptr;
        
        ListNode* slow = pHead;
        ListNode* fast = pHead;
        while(slow!=nullptr && fast->next!=nullptr){
            slow = slow->next;
            fast = fast->next->next;
            if(slow==fast) break;
        }
        if(fast->next==nullptr) return nullptr; // 无环
        
        slow = pHead;
        while(slow!=fast){
            slow = slow->next;
            fast = fast->next;
        }
        return slow;
    }
};
posted @ 2020-03-09 17:37  Flix  阅读(114)  评论(0编辑  收藏  举报