数据结构-剑指offer-链表中环的入口节点

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

思路:

1、确定一个链表中是否包含环。可以定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步,如果走的快的指针追上了走的慢的指针,那么链表就包含环;如果走的快的指针走到了链表的末尾,都没有追上第一个指针,那么链表就不包含环。

2、如何找到环的入口。分两步进行:(1)判断环中节点的数目;(2)找到环的入口。

(1)判断环中节点的数目。在判断一个链表里是否有环时用到了一快一慢的两个指针,如果两个指针相遇,则表明链表中存在环,所以两个指针相遇的节点一定是在环中!可以从这个相遇的节点出发,直到又回到这个节点,就可以得到环中节点数了。

(2)找到环的入口。如果链表中的环有n个节点,则指针P1先在链表上向前移动n步,然后两个指针以相同的速度向前移动。当第二个指针指向环的入口节点时,第一个指针已经围绕着环走了一圈,又回到了入口节点。

函数MeetingNode在链表存在环的前提下找到一快一慢两个指针相遇的节点,函数EntryNodeOfLoop用来找环的入口节点。

class Solution {
private:
    ListNode* MeetingNode(ListNode* pHead){
        if(pHead == nullptr){
            return nullptr;
        }
        ListNode* pSlow = pHead->next;
        if(pSlow == nullptr){
            return nullptr;
        }
        ListNode* pFast = pSlow->next;
        while(pFast != nullptr && pSlow != nullptr){
            if(pFast == pSlow){
                return pFast;
            }
            pSlow = pSlow->next;
            pFast = pFast->next;
            if(pFast != nullptr){
                pFast = pFast->next;
            }
        }
        return nullptr;
    }
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead){
        ListNode* meetingNode = MeetingNode(pHead);
        if(meetingNode == nullptr){
            return nullptr;
        }
        int nodesInLoop = 1;
        ListNode* pNode1 = meetingNode;
        while(pNode1->next != meetingNode){
            pNode1 = pNode1->next;
            nodesInLoop++;
        }
        pNode1 = pHead;
        for(int i=0;i<nodesInLoop;i++){
            pNode1 = pNode1->next;
        }
        ListNode* pNode2 = pHead;
        while(pNode1 != pNode2){
            pNode1=pNode1->next;
            pNode2=pNode2->next;
        }
        return pNode1;
    }
};

猜你喜欢

转载自blog.csdn.net/baidu_32936911/article/details/80309560