leetcode 142. 环形链表 II

188 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

leetcode 142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

  示例 1:

输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。

思路分析:

本题是一道算法题也可以说是一道数学题,首先我们解决这道题需要先确定里面链表里面是否有环存在,如果环存在的情况下,再去寻找环的入口,如何判断环是否存在呢,我们可以通过快慢指针的方式来确定,设置一个慢指针每次走一步,再设置一个快指针每次走两步,如果快慢指针能够相遇,那么就说明链表里面有环。

当我们确定链表里面有环之后,就可以开始寻找环的入口了,我们假设从head到环入口的距离是a,环入口到相遇点的距离是b,环剩余距离是c,因为快指针是慢指针的两倍速,所以当他们相遇时,慢指针走了a+b,快指针走了2*(a+b),那么就可以得出 2*(a+b)=a+(n+1)b+n*c

由此得知a=c+(n-1)(b+c)

因为快慢指针的速度差异得知,假设环为l,快慢指针最大距离l-1,慢指针需要l秒跑完一圈,而快指针每秒可以追1的距离,那么可以得知相遇时,慢指针还未跑过一圈。所以a等于c

那么我们再找到环的相遇点之后,让快指针回到head,并设置相同的速度,那么他们再次相遇时所在点就是环的入口。

实现代码:

var detectCycle = function(head) {
    if(!head)return null
    let slow = head
    let fast = head
    while(fast.next){
        slow = slow.next
        fast = fast.next.next
        if(!fast) return null
        if(fast===slow){
            fast = head
            while(slow!==fast){
                slow = slow.next
                fast = fast.next
            }
            return slow
        }
    }
    return null
};