Leetcode142 - Linked List Cycle II(链表)

本文介绍了一种检测链表中是否存在环并找到环起点的方法。通过快慢指针技巧,当两者首次相遇后,将一指针移至链表头,两指针同步前进直至再次相遇,即为环起点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

给定一个链表,判断这个链表内是否存在环,并且求这个环的起点。

思路

如图所示:
这里写图片描述

我们再假设圆的周长为r,我们需要求的是a。
于是,我们设置两个指针slow和fast,slow每次走一步,fast每次走两步,并且两个都走了t时间,于是:

slow:t=a+b ==>为什么不是t==a+b+mr:因为slow一旦进入环,不会跑超过一圈就会和fast相遇。

fast:2t=a+b+nr

我们可以解得:

nr=a+b

上面式子的意思即:我们从相遇的点C出发,再走a步,能够走到环的起点!即:我们的slow和fast相遇在C点了, 这时候,我们把slow放回起点A,fast放在C点,两个同时开始走且步速均为1,那么我们相遇的点就是B点!

Follow up

  1. 求环的长度

    首先,我们不能从起点到C点的相遇来确定环长,因为之间相差的是环长的若干倍,并且倍数还不能确定。

    但是,当我们第一次在C点相遇后,之后,fast继续走两步,slow继续走一步。再次相遇时,刚好相差一圈。就追及问题。

  2. 将有环链表变成单链表

    我们找到B点之后,记录下B点的位置,然后绕着环走,再次走到B点时结束。

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if (!head) return NULL;
        ListNode *slow = head, *fast = head;
        while (slow && fast) {
            slow = slow->next;
            fast = fast->next;
            if (!fast) return NULL;
            fast = fast->next;
            if (slow == fast) break;
        }
        if (!slow || !fast) return NULL;
        slow = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值