JS算法-环形链表

104 阅读2分钟

题目

给你一个链表的头节点 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
  }

坚持努力,无惧未来!