【路飞】算法与数据结构-环形链表 Ⅱ

145 阅读2分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

给定一个链表,返回链表开始入环的第一个节点。如果链表无环,这返回null。
如果链表中有某个节点,可以通过跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,使用整数pos表示链表尾连接到链表中的位置(索引从0开始)。如果 pos-1,这在该链表中没有环。
不允许修改链表\

例1:

leetcode-lb-II-01.png

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

leetcode-lb-II-02.png

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

leetcode-lb-II-03.png

输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。
复制代码

思路

思路来自官方的Floyd动态规划算法 每次迭代,p0跳一节点,速度1,p1跳双节点,速度2

不存在,p0或p1为null 存在环,p1超p0一圈,相遇图点A,求点B p0的路程:a + b p1的路程:a + b + c + b p1速度是p0的2倍,时间一定,p0的路程 * 2 = p1的路程 (a + b) * 2 = a + b + c + b,解a = c 当p0和p1相遇点A时,新指针从起始点向B走 p0和新指针速度都为1,路程相同,两者终会相遇点B,返回p0指向节点 存在环,p1超p0 n圈,相遇图A,求点B,p1路程:a + b + (c + b) * n。(a + b) * 2 = a + b + (c + b) * n

  • a = (c + b) * n - b = (c + b) * (n - 1) + c + b - b = c + (c + b) * (n - 1)
  • a = c + (n - 1) * 圈,无论超多少圈,最后一圈的情况都与超1圈时相同

代码

var detectCycle = function(head) {
    var p = [head, head]
    while (p[0] && p[1]) {
        p = [p[0].next, p[1].next ? p[1].next.next : null]
        if (p[0] && p[0] === p[1]) {
            while (head) {
                if (p[0] === head) return head
                p[0] = p[0].next, head = head.next
            }
        }
    }
    return null
};