力扣——环形链表找入环点

127 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情

你好,我是南一。这是我在准备面试八股文的笔记,如果有发现错误或者可完善的地方,还请指正,万分感谢🌹

一、题目

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

二、解法:快慢指针

在头节点放快慢指针,当快慢指针相遇,慢指针到入环点的距离与头节点到入环点的距离相等

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

三、解法剖析

1、为什么当快慢指针相遇,慢指针到入环点的距离与头节点到入环点的距离相等?

假设 头节点 到 入环点的距离为 x,入环点到相遇点的距离为 y,相遇点到入环点距离为 z,n 是快指针走过的环的圈数

慢指针走过的距离:x + y

快指针走过的距离:x + y + n ( y + z )

快指针速度是慢指针的两倍:

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

最后结果的意思是,x 和 z 之间的长度差,会是环 ( y + z ) 的整数倍

假如 n = 1,x 和 z 就一样长,在头节点和相遇点各放一个步距为1的指针,他们最终会在入环点相遇

假如 n > 1,x 比 z 长 n - 1 圈的长度,在头节点(a指针)和相遇点(b指针)各放一个步距为1的指针,b指针最终会在环内多绕 n - 1 圈,再与a指针相遇。

回答上方问题: 由公式推理可得,x 和 z 的关系有两种,一种是问题中所说的相等关系,另一种是 x 比 z 长 n - 1 圈的长度。

2、为什么慢指针没有走完一圈?

假设:慢指针走到入环点时,快指针刚好在慢指针前一个节点。

两者间距离为 (环长度 - 1)

快慢指针在环内的追逐,由于快指针总比慢指针多走一步,所以每多走一步,两者间的距离就少一步,

直到相遇,慢指针也只走了 (环长度 - 1) 的距离。我们的假设已经是最坏的情况,所以慢指针不会走完一圈。