给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
如果链表中存在环,则返回 true 。 否则,返回 false 。
方法一:数组缓存
判断链表是否成环,最主要的依据就是在遍历的同时会回到某个已经经历过的节点。可通过将遍历的节点存放在数组中,在便利的同时判断其是否在数组中存在即可。若链表遍历至 null 那么这个链表必定不成环。
代码:
var hasCycle = function(head) {
if (head === null || head.next === null) {
return false
}
let list = []
while(head) {
if (list.indexOf(head) !== -1) {
return true
}
list.push(head)
head = head.next
}
return false
};
方法二:双指针-龟兔赛跑
链表如果存在环,那么这个链表遍历一定是无穷的。如果使用双指针,分别控制指针移动的快慢,那么这两个指针一定会相交!类似于故事中的龟兔赛跑。
图解:
假设存在这样的环形链表
分别在root定义两个指针,代表兔子和乌龟。
兔子和乌龟同时出发,开始遍历,兔子的速度快,每次遍历2格,乌龟的速度慢,每次遍历1格。
如图:
代码实现:
var hasCycle = function(head) {
let slow = head
let quick = head
while(quick && quick.next !== null && quick.next.next !== null) {
quick = quick.next.next
slow = slow.next
if (quick === slow) {
return true
}
}
return false
}