代码随想录-142环形链表

文章介绍了如何使用快慢指针来检测链表中是否存在环,以及如何找到环的入口节点。当快指针和慢指针相遇时,它们的相对位置揭示了环的结构,并可以通过再次从相遇点出发,同步移动两个指针来找到环的起始点。这种方法基于快指针比慢指针多移动一倍的距离,因此在环中相遇时,快指针已经比慢指针多走了一圈。
摘要由CSDN通过智能技术生成

142环形链表

本题的技巧是使用快慢指针

慢指针的移动速度为1,快指针的移动速度为2,如果链表里不存在环,那么快指针会先走到链表末尾(即nullptr)位置。以下我们讨论当链表里存在环的解法。
图1.示意图
如图1所示,假设红色点a为链表进入环的第一个节点,蓝色点b为快慢指针相遇的地方。我们假设三段距离分别为 x x x, y y y, z z z。假设当快指针追上慢指针时,快指针已经在环内走了 n n n圈。则有以下等式成立:

2 ( x + y ) = x + n ( y + z ) + y 2(x+y) = x + n(y+z) + y 2(x+y)=x+n(y+z)+y

即慢指针走过的路程的两倍等于快指针走过的路程,整理一下可得到:
x = n ( y + z ) − y = ( n − 1 ) ( y + z ) + z x = n(y+z) - y = (n-1)(y+z) + z x=n(y+z)y=(n1)(y+z)+z

这个等式具有特殊的含义,它表示如果两个指针分别从链表开始和b节点以相同的速度出发,从b出发的指针在走(n-1)圈之后,最终会在节点a和另一个相遇,而节点a刚好是题目中要求的链表开始入环的第一个节点。

如何找到节点b呢?注意节点b是快慢指针在环里第一次相遇的位置,快指针和满指针相等时的节点位置就是b。

整体代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode * slow = head;
        ListNode * fast = head;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            // 快慢指针相遇时,即找到b点
            if(fast == slow){
                ListNode * p = head;
                //让p和slow指针同时出发
                while(p != slow){
                    p = p->next;
                    slow = slow->next;
                }
                return p;
            }
        }
        return NULL;
    }
};

在第一个等式里,为什么慢指针在进入环的第一圈就能和快指针相遇。如果慢指针在进入环时就和快指针相遇,这种情况显然满足在第一圈相遇。我们假设一种比较极端的情况,当慢指针进入环时,快指针刚好在其前方一个节点位置,此时快指针要追赶慢指针,为方便理解,我们把环拉直,如下图所示,每一个线段表示一个环。当慢指针走完一圈时(蓝色线段),由于快指针走的路程是慢指针的两倍,此时快指针的位置一定在慢指针前面(红色线段),在这个过程中,快指针和慢指针一定在某个时刻“擦肩而过”。
图2.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值