返回

用JavaScript 刷 LeetCode 第 86 题:分隔链表,难度系数 up up up

前端

作为一个 JavaScript 开发者,你可能会觉得 LeetCode 第 86 题,也就是「分隔链表」这道题非常简单。毕竟,它只要求你将一个链表根据一个给定的值进行分割,将小于该值的所有节点放在前面,而大于或等于该值的节点放在后面。

然而,当你实际动手写代码时,可能会发现事情并不像你想象的那么容易。就像「Talk is easy, show me your code」这句话所表达的,只有真正写出代码,你才会发现问题的复杂性。

初见 LeetCode 86:小试牛刀,信心满满

当你第一次看到 LeetCode 86 题时,你可能会信心满满。你心想,这道题不就是将链表中的节点按照一个给定的值进行分割吗?这对我来说简直是小菜一碟。于是,你撸起袖子,开始写代码:

const partition = (head, x) => {
  let smallHead = null;
  let smallTail = null;
  let largeHead = null;
  let largeTail = null;

  while (head) {
    if (head.val < x) {
      if (!smallHead) {
        smallHead = head;
        smallTail = head;
      } else {
        smallTail.next = head;
        smallTail = head;
      }
    } else {
      if (!largeHead) {
        largeHead = head;
        largeTail = head;
      } else {
        largeTail.next = head;
        largeTail = head;
      }
    }

    head = head.next;
  }

  if (smallHead) {
    smallTail.next = largeHead;
  } else {
    return largeHead;
  }

  return smallHead;
};

你兴致勃勃地将这段代码提交到 LeetCode,却发现它报了一个错误:环形链表。

痛定思痛:环形链表的启示

看到这个错误,你开始反思自己的代码。你意识到,在你分割链表时,如果存在环形链表,那么你的程序就会陷入无限循环,最终导致程序崩溃。

为了解决这个问题,你需要在代码中加入一个检查环形链表的机制。你可以使用哈希表或快慢指针来判断链表中是否存在环。

// 在分割链表之前,检查是否存在环形链表
const hasCycle = (head) => {
  let slow = head;
  let fast = head;

  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;

    if (slow === fast) {
      return true;
    }
  }

  return false;
};

// 如果存在环形链表,则返回 null
if (hasCycle(head)) {
  return null;
}

再战 LeetCode 86:吸取教训,谨慎前行

吸取了上一次的教训,你再次修改代码,加入了环形链表的检查机制:

const partition = (head, x) => {
  // 如果存在环形链表,则返回 null
  if (hasCycle(head)) {
    return null;
  }

  let smallHead = null;
  let smallTail = null;
  let largeHead = null;
  let largeTail = null;

  while (head) {
    if (head.val < x) {
      if (!smallHead) {
        smallHead = head;
        smallTail = head;
      } else {
        smallTail.next = head;
        smallTail = head;
      }
    } else {
      if (!largeHead) {
        largeHead = head;
        largeTail = head;
      } else {
        largeTail.next = head;
        largeTail = head;
      }
    }

    head = head.next;
  }

  if (smallHead) {
    smallTail.next = largeHead;
  } else {
    return largeHead;
  }

  return smallHead;
};

这一次,你的代码顺利通过了 LeetCode 的测试。你终于体会到了「失败是成功之母」的真谛。

回顾与展望:从 LeetCode 86 题中学到的经验

通过解决 LeetCode 86 题,你不仅收获了算法上的知识,还明白了在编程实践中谨慎思考和检查的重要性。以下是你可以从这道题中学到的经验:

  • 不要轻视任何问题,即使它看起来很简单。 很多时候,简单的问题往往隐藏着意想不到的复杂性。
  • 在动手写代码之前,先思考清楚问题的解题思路。 明确的思路可以让你避免走弯路,写出更优雅、更有效的代码。
  • 养成检查代码的习惯,尤其是在处理链表这类容易出现环形链表的数据结构时。 通过加入环形链表的检查机制,你可以避免程序陷入死循环,提高代码的鲁棒性。

希望你从这篇文章中学到的经验可以帮助你成为一名更好的 JavaScript 开发者。继续加油,勇攀编程高峰!