剑指Offer(牛客版)--面试题23:链表中环的入口节点

 

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

 

分析:

 

完整代码:

 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        //在链表中寻找一个节点作为起始点
        ListNode* pstart = MeetNode(pHead);
        //判断该节点是否存在
        if(pstart == nullptr)//如果不存在,则说明链表中不存在环
            return nullptr; 
        /******计算链表中环的长度*******/
        //节点的数量
        int length = 1;
        // 当下位置标记指针
        ListNode* pNode = pstart;
        //如果当前的节点不是起始点
        while(pNode->next != pstart)
        {
            //一直往下遍历
            pNode  = pNode->next;
            //节点数+1
             length++;
        }
        //*******计算链表中的入口节点*******/
        // 创建前指针
        ListNode* pNode1 = pHead;
        //让前指针先走length步
        for(int i = 0; i < length;i++)
        {
            pNode1 = pNode1->next;
        }
        //创建后指针
        ListNode* pNode2 = pHead;
        //判断两指针是否相遇
        while(pNode1 != pNode2)
        {
            //两个节点同步往前走
            pNode1 = pNode1->next;
            pNode2  = pNode2->next;
        }
        // 返回环的入口节点
        return pNode1;
    }
private:
      //判断链表中是否存在环
      ListNode* MeetNode(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;
     }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值