链表中环的入口结点

题目描述

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

思路

1、首先判断链表中是否有环。利用快慢指针,即快指针一次移动两步,慢指针一次移动一步,如果链表中有环,那么快慢指针迟早会相遇。所以以快慢指针是否会相遇为条件判断链表中是否有环。
在这里插入图片描述
2、如果有环,找环的入口点。如上图所示,起点为S,环的入口点为A,快慢指针的相遇结点为B,假设快慢指针在环中顺时针移动。其中SA的距离、AB的距离及BA的距离分别为x,y,z。设c=y+z为环的长度。则有:
快指针走过的路程:sFast=x+nc+y(n为快指针在环中以A为起点绕的整数倍的圈数)
慢指针走过的路程:sSlow=x+mc+y(m为慢指针在环中以A为起点绕的整数倍的圈数)
因为快指针一次移动两步,慢指针一次移动一步,所以快慢指针相遇时,快指针走过的路程是慢指针的两倍,即sFast=2*sSlow。将上面的两个式子带入到这个等式中,得:
x = (n-2m)c-y = (n-2m-1)c+c-y = (n-2m-1)c+z
即S到A的距离等于数倍的环长加B到A的距离,也就是说,如果设置两个指针p,q,p指向起点S,q指向相遇点B(第一步快慢指针相遇的点),两个指针同时前进且步长都是1,那么这两个指针最终会在入口点A相遇(p走到A,q走了(n-2m-1)倍的环长回到B,又从B走到了A)。

代码(c++)

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL||pHead->next==NULL||pHead->next->next==NULL) return NULL;
        ListNode* pFast=pHead->next->next;
        ListNode* pSlow=pHead->next;
        while(pFast!=pSlow){
            if(pFast->next!=NULL&&pFast->next->next!=NULL){
                pFast=pFast->next->next;
                pSlow=pSlow->next;
            }
            else return NULL;
        }
        pFast=pHead;
        while(pFast!=pSlow){
            pFast=pFast->next;
            pSlow=pSlow->next;
        }
        return pFast;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值