题目
给你一个链表的头节点 head
,判断链表中是否有环。
输入: head = [3,2,0,-4], pos = 1 输出: true 解释: 链表中有一个环,其尾部连接到第二个节点。
题解
第一种
首先,若链表头节点head为空,直接返回false,表示不存在环。接下来定义一个储存节点的WeakSet数据结构,用于存储已经遍历的节点。然后定义一个flag变量赋值为true,作为最终的返回结果。接着进入一个while循环,循环条件为true,也就是一直进行循环,直到break语句触发。在while循环中,首先判断当前节点是否已经被WeakSet存储过,如果是,说明链表存在环,直接break退出循环;否则,将当前节点加入WeakSet中。接着判断当前节点的下一个节点是否为空,如果为空,说明链表已经遍历到了末尾,将flag变量改成false,跳出循环。如果下一个节点不为空,就将当前节点的下一个节点赋值给next,继续循环。最后,返回flag变量,表示链表是否存在环。
var hasCycle = function(head) { if (!head) return false let next = head const weakset = new WeakSet() let flag = true while(true) { if (weakset.has(next)) break; weakset.add(next) if (!next.next) { flag = false break; } next = next.next } return flag };
第二种
我们这里使用快慢指针的方式检测链表是否有环。先判断链表是否为空或者只有一个节点,如果是,则一定没有环。接着定义三个指针,i、j、k,i每次走一步,j每次走两步,k每次也走两步。如果链表存在环,那么i与j一定会相遇,此时将k初始化为head,然后k与i、j同步走,当k与i(或j)相遇时,就证明链表有环。如果k在走的过程中发现链表末尾,也就是k.next或k.next.next为null,则证明链表是一个无环链表,直接返回false即可。最终,如果循环结束了,也没有发现链表存在环,则返回false。
var hasCycle = function (head) { if (head === null || head.next === null) { return false } let i = head.next, j = head, k = head while (i !== null) { if (k.next === null || k.next.next === null) { return false } k = k.next.next if (k === i || k === j) { return true } i = i.next j = j.next } return false }