链表 · 4/7

合并有序链表

将两个升序链表合并为一个升序链表

问题

给定两个升序排列的链表,将它们合并为一个新的升序链表并返回。

示例:

  • 输入:1 -> 2 -> 41 -> 3 -> 4
  • 输出:1 -> 1 -> 2 -> 3 -> 4 -> 4

解答

链表节点定义

class ListNode {
  constructor(val = 0, next = null) {
    this.val = val;
    this.next = next;
  }
}

迭代法

function mergeTwoLists(l1, l2) {
  // 创建虚拟头节点,简化边界处理
  const dummy = new ListNode(-1);
  let current = dummy;

  // 同时遍历两个链表
  while (l1 !== null && l2 !== null) {
    if (l1.val <= l2.val) {
      current.next = l1;
      l1 = l1.next;
    } else {
      current.next = l2;
      l2 = l2.next;
    }
    current = current.next;
  }

  // 拼接剩余部分
  current.next = l1 !== null ? l1 : l2;

  return dummy.next;
}

递归法

function mergeTwoLists(l1, l2) {
  // 递归终止条件
  if (l1 === null) return l2;
  if (l2 === null) return l1;

  // 选择较小的节点,递归处理剩余部分
  if (l1.val <= l2.val) {
    l1.next = mergeTwoLists(l1.next, l2);
    return l1;
  } else {
    l2.next = mergeTwoLists(l1, l2.next);
    return l2;
  }
}

测试代码

// 辅助函数:数组转链表
function arrayToList(arr) {
  const dummy = new ListNode();
  let current = dummy;
  for (const val of arr) {
    current.next = new ListNode(val);
    current = current.next;
  }
  return dummy.next;
}

// 辅助函数:链表转数组
function listToArray(head) {
  const result = [];
  while (head) {
    result.push(head.val);
    head = head.next;
  }
  return result;
}

// 测试
const l1 = arrayToList([1, 2, 4]);
const l2 = arrayToList([1, 3, 4]);
const merged = mergeTwoLists(l1, l2);

console.log(listToArray(merged)); // [1, 1, 2, 3, 4, 4]

关键点

  • 使用虚拟头节点(dummy node)避免处理头节点的特殊情况
  • 迭代法时间复杂度 O(m+n),空间复杂度 O(1)
  • 递归法时间复杂度 O(m+n),空间复杂度 O(m+n)(递归栈)
  • 循环结束后记得拼接未遍历完的链表
  • 两种方法都不需要创建新节点,直接调整指针即可