剑指Offer——面试题23:链表中环的入口节点

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
在这里插入图片描述

算法分析

当用一个指针难以解决问题时,可以尝试用多个指针分析。

假如我们能够知道环上结点的数目 n , 设置指针 pNode1 和 pNode2,pNode2 先走 n 步,之后 pNode1 和 pNode2 开始遍历,当 pNode1 == pNode2 时,即为入口节点。

具体来讲:

  • 设置两个指针 p1 和 p2,每次 p1 走一步, p2 走两步,如果存在环,则 p1 和 p2 在若干步操作后就会相遇。此步骤可以判断是否有环存在
  • 分析环存在与否对应的解决方案
    • 当没有环存在时,返回 nullptr;
    • 当有环存在时:
      • 首先确定环上结点的个数,比如图3.8中结点个数为4:具体来讲,从 p1 和 p2 相遇的地址开始,向后遍历并累计结点数目 n,直到再次回到相遇的地址。
      • 寻找入口:设置指针 pNode1 和 pNode2,pNode2 先走 n 步,之后 pNode1 和 pNode2 开始遍历,当 pNode1 == pNode2 时,即为入口节点。

程序代码

切勿忘记代码的鲁棒性,即要对特殊情况予以特殊处理。

/*
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* rep = IsOfLoop(pHead);
        unsigned int Count = 1;
 
        if(rep == nullptr)
            return nullptr;
        else
        {
            ListNode* pNode1 = pHead;
            ListNode* pNode2 = pHead;
            unsigned int NodeStep = 0;
            ListNode* findp = rep;
            //确定环的节点个数
            while(findp->next != rep)
            {
                Count++;
                findp = findp->next;
            }
            //pNode2移动Count个节点
            while(NodeStep < Count)
            {
                pNode2 = pNode2->next;
                NodeStep++;
            }
            //确定入口
            while(pNode1 != pNode2)
            {
                pNode1 = pNode1->next;
                pNode2 = pNode2->next;
            }
            return pNode1;
             
        }
    }
    ListNode* IsOfLoop(ListNode* pHead)
    {
        ListNode* p1 = pHead;//慢指针
        ListNode* p2 = pHead;//快指针
        while(1)
        {
            int step = 0;
            while(step < 2)
            {
                p2 = p2->next;
                step++;
                if(p2 == nullptr)
                    return nullptr;
            }
            p1 = p1->next;
             
            if(p1 == p2)
                return p1;
        }
    }
};

总结:

多指针来解决链表的复杂问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值