【Daily Interview】- 06 环形链表

162 阅读2分钟

题目

图片1
图片1

!! 题目来源:环形链表 - 力扣

分析

首先简单介绍一下链表这个数据结构:所谓链表,就是一连串拥有着指向下一个节点的指针的节点集。

这么说可能有点绕,不过看一个图大家就明白了:

图片2
图片2

那么如果要用 Javascript 来实现一个链表,如下即可:

class LinkList {
  constructor(value) {
    this.value = value
    this.next = null
  }
}

可以看到,标准的链表是单向的,如果要找到其中某一个节点,只能从头往后依次查找,而所谓环形链表,就是有节点的 next 指向前方某个节点,从而形成了一个环:

图片3
图片3

那么怎么判断一个链表是否为环形链表呢?

其实也很简单:

  • 创建一个 cache,每次遍历一个 node,便将其存入 cache
  • 每次遍历 node 的时候,查找 cache 中是否有自身
    • 如果有,则说明是环形链表
    • 如果遍历完也没有,则不是环形链表
const hasCycle = head => {
  const cache = new Set()
  while (head) {
    if (cache.has(head)) {
      return true
    } else {
      cache.add(head)
    }
    head = head.next
  }
}

结果如下:

图片4
图片4

进阶

图片5
图片5

此限制就是不允许使用 cache

换个思路:我们知道,当再操场上跑圈的时候,如果有快有慢,那么总有那么一刻,跑的快的人会从背后追上跑得慢的人。

那么我们把这个思路应用到这里:

  • 假设跑得慢和跑得快的节点分别是 slowfast,其中 slow 的步长为 1,而 fast 为 2
  • 那么在遍历完这个节点之前,一旦 slow == fast,则说明此链表存在环

具体代码如下:

const hasCycle = head => {
  let slow = head
  let fast = head
  while (fast && fast.next) {
    slow = slow.next
    fast = fast.next.next
    if (slow === fast) return true
  }
  return false
}

结果如下:

图片6
图片6