链表 141. 环形链表

Posted by CodingWithAlice on June 5, 2021

链表 141. 环形链表

总结:

  • ①最基础的方法:双指针循环(性能差)
  • ②投机法:Json.stringify(head),利用该序列化方法自带的「有互相引用就报错」
  • ③给链表加个 tag【最优】:给每个节点加标记
  • ④利用 set 作为哈希表
function circleTag3(head) {
    while(head) {
        if(head.tag) {
            return true;
        }
        head.tag = true;
        head = head.next;
    }
    return false
}
function circleHash4(head) {
    let set = new WeakSet();
    while(head) {
        if(set.has(head)) {
            return true;
        }
        set.add(head);
        head = head.next;
    }
    return false
}

力扣 141. 环形链表

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

  • 1、自己的算法:非常耗费内存,导致力扣不给我过…

但是我跑了报错的测试用例…只要内存够…我的算法返回的结果是正确的

var hasCycle = function(head) {
    if (head === null || head.next === null) {
        return false;
    }
    let circle = false;
    let arr = [head.val]; // 用两个数组存储当前节点和下一个节点的值
    let arrNext = [head.next.val];
    // 遍历链表每一项,判断是否和之前的节点相同
    for(let i = head.next; i.next !== null && !circle; i = i.next) {
        // 在 arr 存在且 arr 和 arrNext 的下标相等
        if (arr.includes(i.val) && (arr.indexOf(i.val) === arrNext.indexOf(i.next.val))) {
            circle = true;
            return circle;
        }
        arr.push(i.val);
        arrNext.push(i.next.val);
    }
    return circle
}
// 两个指针,但是性能太差
var hasCycle = function (head) {
    let cursor1 = head;
    let cursor2 = head.next;
    if (!cursor1 || !cursor2) { return false }
    while (cursor1) {
        while (cursor2) {
            if (cursor2.value === cursor1.value) {
                return true
            }
            cursor2 = cursor2.next;
        }
        cursor1 = cursor1.next;
    }
    return false
};
  • 2、我觉得有点神奇的/投机的方法

image-20210607101412499

时间复杂度:O(n),空间复杂度:xx

【查了下JSON.stringify()原理也是要遍历参数进行处理的】

// 除非不报错,报错就是有环
var hasCycle = (head) => {
  try {
    JSON.stringify(head);
  } catch (error) {
    return true
  }
  return false
}

补充: JSON.stringify()方法对循环引用本身就会报错,截图来源于 MDN

image-20210607140736619

  • 3、我觉得还不错的算法

image-20210607113630229

时间复杂度:O(n),空间复杂度:xx

var hasCycle = (head) => {
  while (head !== null) {
    // 出现已经标记过的节点就代表有重复节点,存在环
    if(head.tag) {
    	return true
    }
    // 给每一个节点打标记
    head.tag = true;
    head = head.next;
  }
  return false
}
  • 4、按照官方提示,哈希表的思维算法

image-20210607141925530

var hasCycle = (head) => {
  // Set中的元素只会出现一次
  let set = new Set();
  while(head !== null){
    // 判断是否存在过
    if(set.has(head)) {
      return true;
    }
    // 添加到 set 中
    set.add(head);
    head = head.next;
  }
  return false
}