返回

再探剑指 Offer 025: 合并两个排序的链表(javascript版)

前端

算法概述

剑指 Offer 025 要求我们合并两个已经排序的链表,并生成一个新的排序链表。为了解决这个问题,我们需要一种高效的方法来比较和合并两个链表的节点。

解决思路

  1. 初始化:

    • 首先,我们创建一个新的链表头节点作为合并后的链表的头节点。
    • 然后,我们定义两个指针 curr1 和 curr2,分别指向两个输入链表的头节点。
  2. 比较和合并:

    • 进入一个 while 循环,只要 curr1 和 curr2 都不是空节点,就继续执行循环。
    • 在循环体内,我们比较 curr1 和 curr2 所指向的节点的值,将较小的节点的值插入到合并后的链表中。
    • 然后,我们让 curr1 和 curr2 指向各自链表的下一个节点。
  3. 处理剩余节点:

    • 当 curr1 和 curr2 中有一个为空节点时,我们将剩余的节点直接连接到合并后的链表的末尾。
  4. 返回合并后的链表:

    • 最后,我们将返回合并后的链表的头节点。

复杂度分析

  • 时间复杂度:O(n + m),其中 n 和 m 分别是两个输入链表的长度。
  • 空间复杂度:O(1),因为我们没有使用额外的空间来存储临时数据。

优缺点

  • 优点:

    • 该算法的时间复杂度是线性的,非常高效。
    • 它不需要额外的空间来存储临时数据,因此空间复杂度为常数。
    • 该算法非常容易理解和实现。
  • 缺点:

    • 该算法可能会在某些情况下产生一个新的链表,而不是修改其中一个输入链表。
    • 如果两个输入链表非常长,可能会导致栈溢出。

示例代码

function mergeTwoLists(head1, head2) {
  if (head1 === null) {
    return head2;
  }
  if (head2 === null) {
    return head1;
  }

  let mergedHead;
  if (head1.val < head2.val) {
    mergedHead = head1;
    head1 = head1.next;
  } else {
    mergedHead = head2;
    head2 = head2.next;
  }

  let current = mergedHead;

  while (head1 !== null && head2 !== null) {
    if (head1.val < head2.val) {
      current.next = head1;
      head1 = head1.next;
    } else {
      current.next = head2;
      head2 = head2.next;
    }

    current = current.next;
  }

  if (head1 !== null) {
    current.next = head1;
  }

  if (head2 !== null) {
    current.next = head2;
  }

  return mergedHead;
}

总结

剑指 Offer 025 是一个经典的合并两个排序链表的算法问题。它要求我们合并两个已经排序的链表,并生成一个新的排序链表。通过本文的详细讲解,我们掌握了如何使用JavaScript解决这个问题。