题目
!! 题目来源:环形链表 - 力扣
分析
首先简单介绍一下链表这个数据结构:所谓链表,就是一连串拥有着指向下一个节点的指针的节点集。
这么说可能有点绕,不过看一个图大家就明白了:
那么如果要用 Javascript 来实现一个链表,如下即可:
class LinkList {
constructor(value) {
this.value = value
this.next = null
}
}
可以看到,标准的链表是单向的,如果要找到其中某一个节点,只能从头往后依次查找,而所谓环形链表,就是有节点的 next 指向前方某个节点,从而形成了一个环:
那么怎么判断一个链表是否为环形链表呢?
其实也很简单:
- 创建一个
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
}
}
结果如下:
进阶
此限制就是不允许使用 cache。
换个思路:我们知道,当再操场上跑圈的时候,如果有快有慢,那么总有那么一刻,跑的快的人会从背后追上跑得慢的人。
那么我们把这个思路应用到这里:
- 假设跑得慢和跑得快的节点分别是
slow和fast,其中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
}
结果如下: