leetcode 142.环形链表 II

本文详细介绍了如何使用快慢指针检测链表中的环,并阐述了寻找环路入口节点的数学原理。通过设定快指针每次前进两步,慢指针每次前进一步,当两者相遇时确定存在环路。接着,从相遇点开始的一个指针重新回到链表头,两者再次相遇即为环的入口。代码示例展示了这一过程,帮助理解该算法的实现细节。
摘要由CSDN通过智能技术生成

首先,对于环形链表题,毫不犹豫,直接快慢指针(需要作解释的是,本题当然也可以使用哈希表进行解答,但在这里我们关注的是快慢指针的方法,并且快慢指针的空间复杂度也更低),具体做法为:

  • 创建两个指针:快指针和慢指针,初始化都指向链表头节点
  • 快指针每次走两步,慢指针每次只走一步

这样,如果链表存在环路,快慢指针终将会在环内的一个节点相遇(注意,不一定是环入口节点)。其实这个思想很好理解,就比如在一个环形跑道跑步,假设有两个人同时在起点,一个跑的快一些,一个跑得慢一些,并且两人都是匀速的,那么两人一定会在跑圈的一个地方再次相遇。这个思想就可以用于检测链表的环路。

本题的难点就是,如何寻找环的入口节点,因为快慢指针相遇的点并不一定是环入口节点。接下来,讲一下我对本题寻找环入口方法的理解:

  • 将一个带环链表分为三部分:x = 从表头到环入口的节点个数;y = 从换入口节点到两指针相遇处的节点个数;z = 从相遇处到环入口的节点个数,其中很容易得到:y + z 为环的节点总个数
  • 所以在慢指针和快指针相遇时,两指针构成的节点个数关系是:(慢)2 * (x + y) =(快)x + n * (z + y) + y。以上等式的解释:等式左边,因为快指针每次都比慢指针快两倍,所以是乘以2;等式右边,相当于走了x步到达入口处时,经过了n圈后,再从入口处走y步相遇
  • 所以,x = (n - 1) * y + n * z = (n - 1)(y + z) + z。 以上等式说明了,从表头走到环入口节点的个数等于指针相遇点走 (n - 1)圈,再走z步的个数
  • 注意,因为这里假设了链表存在环,所以 n>=1!

到此就解释了,为什么一个指针从表头开始遍历,另一个指针从从相遇点开始遍历,那么它们必定会相遇

以下是本题的解答代码(java):

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null) return null;
        ListNode p = head, q = head;
        //如果有环,找到一个环内的节点
        while(q != null && q.next != null) {
            p = p.next;
            q = q.next.next;
            if(p == q) break;
        }
        //该链表无环
        if(q == null || q.next == null) return null;
        //一个指针从链表头开始遍历,一个指针从环内的一个节点开始遍历,他们一定会在环的入口相遇。解释?
        p = head;
        //找环入口
        while(p != q) {
            p = p.next;
            q = q.next;
        }
        return q;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值