链表 141. 环形链表

Posted by CodingWithAlice on June 5, 2021

链表 141. 环形链表

力扣 141. 环形链表

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

image-20210605194914137

进阶:

你能用 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
}
  • 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
}