【LeetCode LCR 022】【C语言】环形链表 II

注意:请务必看完以下技术内容再来做这道题【LeetCode例141】【c语言】环形链表-CSDN博客

1 题目介绍

        给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null

        为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

        说明:不允许修改给定的链表。

示例1:

        输入以下链表,值为3的节点为head节点

        返回值应该为值为2的节点

示例2:

        输入以下链表,值为1的节点为head节点

        返回值应该为值为1的节点

示例3:

        输入以下链表,值为1的节点为head节点

        

        返回值应该为NULL

        照例放上题目链接: . - 力扣(LeetCode)

2 解题思路

        我们首先先判断这个链表是否带环,这里就不多赘述了,如果不太清楚的话可以看文章开头链接的内容

        判断完链表是否带环之后我们就可以得到重合在一起的 fast slow 指针

 

        不难看出,此时fast或者slow到入口节点的距离与head到入口节点的距离相等!

        那么我们只要在此时同时遍历slow和head,让其重合就能找到入口节点!

 3 实现代码

typedef struct ListNode ListNode;

struct ListNode *detectCycle(struct ListNode *head) 
{
    if(head == NULL || head->next == NULL)
    {
        return NULL;
    }

    ListNode* fast = head;
    ListNode* slow = head;

    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            ListNode* meet = head;
            for(meet = head; meet != slow; meet = meet->next, slow = slow->next)
                ;
            return meet;
        }
    }
    return NULL;
}

4 关于本题的思考

        事实上,本体如何解并不是我们关注的重点,我们关注的重点应该是为什么本题可以这么解,以至于我们得讨论一个数学问题

·我们设 head 到入口的距离为L,slow / fast 到入口的距离为M, 整个环的周长为C

·那么除开M的距离,一个环剩下的距离应该是C-M

·因为我们不知道 fast 在环里面走了几圈才遇到 slow ,所以我们再设 fast 走的圈数为 k(在以下这个例子里,fast 走了两圈不到,完整的圈只有1,所以 k 为 1)

        我们都直到 fast 的速度时 slow 的两倍,所以 fast 走过的路程一定是 slow 的两倍

        因此我们可以得到公式

                                        2 * (L + C - M) = L + k * C + (C - M)

                    左边是2 * slow 走的距离     =     右边是 fast 走的距离

           带入k并化简可得:                   L = M       

                 即得证,fast或者slow到入口节点的距离与head到入口节点的距离相等

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值