LeetCode探索(八):21_合并两个有序链表

845 阅读2分钟

这是我参与11月更文挑战的第 15 天,活动详情查看:2021最后一次更文挑战

前言

在数据结构和算法中,链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。

链表由一系列结点(节点)组成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间。

下面我们通过一道 LeetCode 题目来了解链表的特点以及应用。

题目

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]

  • -100 <= Node.val <= 100

  • l1l2 均按 非递减顺序 排列

思考

对于这道题,首先可以想到的是我们逐个去比较两个链表的节点,每次取出较小的节点,然后将剩下的节点继续进行比较。思路不是很难,那么代码应该怎么写呢?我们可以借助递归去书写代码。

此外,要考虑边界情况。如果存在空链表的情况,那么我们只需要返回非空链表即可。如果两个链表中有一个为空,递归结束。

下面是具体的代码。

解答

递归

/**
 * @author 觅迹
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var mergeTwoLists = function(l1, l2) {
  if (l1 === null) { // l1节点为空
    return l2;
  } else if (l2 === null) { // l2节点为空
    return l1;
  } else if (l1.val < l2.val) { // 取出较小的节点
    l1.next = mergeTwoLists(l1.next, l2);
    return l1;
  } else { // 取出较小的节点
    l2.next = mergeTwoLists(l1, l2.next);
    return l2;
  }
};

复杂度分析:

  • 时间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。

  • 空间复杂度:O(n + m)。

参考