链表中环的入口结点

题目描述

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

问题分析:设置两个指针,pSlow初始化为pHead,在后,走的慢;pFast初始化为pHead->next,在前,走的快,二者一定会在环内相遇;二者相遇之后设置计数器,令指针沿着环走一圈,计算环中元素数量;设置两个指针p1和p2,令p1先走环中元素数量的位置,然后两个同时走,二者会在环入口相遇

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
       if(pHead==NULL)return NULL;
         //先计算环中结点的个数
         //快慢指针相遇结点一定在环中
        //每向前走一步,检验是否为空,避免链表不是环的时候,程序出错
         ListNode *pSlow=pHead,*pFast=pHead->next;
         while(pFast!=NULL&&pSlow!=NULL)
         {
            pSlow=pSlow->next;
            pFast=pFast->next;
            if(pFast==pSlow) break;
            if(pFast!=NULL)
                pFast=pFast->next;
         }
         //开始统计环结点数
         int countNum=1;
         ListNode *pTempNode=pFast->next;
         if(pFast==pSlow&&pFast!=NULL)
         {
             while(pTempNode!=pFast)
             {
                 pTempNode=pTempNode->next;
                 ++countNum;
             }
         }
         else
             return NULL;
         //再设两指针,一先一后
         ListNode *p1=pHead,*p2=pHead;
         for(int i=0;i<countNum;i++)
                p1=p1->next;
         while(p1!=p2)
         {
             p1=p1->next;
             p2=p2->next;
         }
         return p1;
    }
};

改进方法:

在 fast 和 slow 同时指向 pHead 时,当二者相遇时,直接令 fast 指向 pHead,二者同步向前走,相遇时就是环的入口。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        if(pHead == NULL)
            return NULL;
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        while (fast != NULL && slow != NULL){
            slow = slow->next;
            if (fast->next != NULL)
                fast = fast->next->next;
            else
                return NULL;
            if (slow == fast)
                break;
        }
        fast = pHead;
        while(fast != slow){
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值