算法-唤醒链表

elegantYU 发布于

第五天

题目

给定一个链表,判断链表中是否有环。

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

如果链表中存在环,则返回 true 。 否则,返回 false 。

示例:

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

原题传送门

思考

给出一个链表,要求判断是否存在循环的链表,题目给出的 pos 是帮助理解题意,并非是传入条件。

  1. 使用 map 存储递归的每个节点,并判断
  • 递归内容:判断 map 中是否存在此节点
  • 返回条件: 参数 link 为 null,或者 map 中存在此节点的下个节点
  • 返回内容: 返回 link.next 继续执行
function hasCycle(link, map = new Map()) {
    if (!link) return false;

    if (map.has(link.next)) {
        return true;
    } else {
        map.set(link.next);
    }

    return hasCycle(link.next, map);
}
  1. 快慢指针,标准解法

快慢指针,设立慢指针指向 head,快指针指向 head.next。

开始循环时,快指针每次都要多走一步,快指针永远会比慢指针先走,若是遇到环形指针,则两者都会进入循环,由于快指针每次都多走一步,所以他俩终将相遇。

若是没有循环,则快指针会先触底。

追及问题

function hasCycle(link) {
    let slow = link;
    let fast = link.next;

    while (!fast && !fast.next) {
        if (slow === fast) {
            return true;
        }

        slow = slow.next;
        fast = fast.next.next;
    }

    return false;
}

我哭了 空间复杂度 O(1)

牛逼

  1. 神奇解法 JSON.stringify
function hasCycle(link) {
    try {
        JSON.stringify(link);
    } catch (e) {
        return true;
    }

    return false;
}

后面继续跟一题 获取链表中间节点的题 深化快慢指针的思路