返回

极简攻略:LeetCode [21] 合并两个有序链表

闲谈

前言

在LeetCode的广阔题海中,[21] 合并两个有序链表是一道经典题。它不仅考察了我们对链表的基本操作,还要求我们理解递归的思想。本文将带你从零入门,层层深入,透彻理解这道题目的精髓。

链表简介

链表是一种常见的数据结构,它由一系列相互连接的节点组成。每个节点包含两个部分:数据域和指针域。数据域存储数据,指针域存储下一个节点的地址。链表具有以下特点:

  • 灵活性强: 链表可以根据需要动态地增加或删除节点,而无需重新分配内存。
  • 插入和删除效率高: 在链表中插入或删除一个节点只需要改变指针,而不需要移动数据。
  • 空间利用率低: 链表的每个节点都包含一个指针域,这会占用额外的空间。

递归的含义

递归是一种函数在运行时调用自身的方法。它通常用于解决那些具有自相似结构的问题。递归函数必须具有以下两个要素:

  • 递归调用: 函数在运行时调用自身。
  • 终止条件: 函数必须有一个或多个终止条件,否则它将无限地调用自身,导致程序崩溃。

升序链表的定义

升序链表是指一个链表中的元素从小到大排列。升序链表通常用于存储有序的数据,例如学生成绩、商品价格等。

合并两个有序链表

现在,我们已经掌握了链表、递归和升序链表的基础知识,就可以开始解决[21] 合并两个有序链表这道题了。

这道题的目的是将两个升序链表合并成一个新的升序链表。合并后的链表应该包含两个原链表的所有元素,并且元素仍然保持升序。

合并算法

我们可以使用递归来解决这道题。递归算法的步骤如下:

  1. 如果两个链表都为空,则返回一个空链表。
  2. 如果其中一个链表为空,则返回另一个链表。
  3. 比较两个链表的头节点的数据,较小的那个节点成为合并后链表的头节点。
  4. 将较小节点的下一个节点作为合并后链表的下一个节点,然后递归地合并剩下的两个链表。

终止条件

递归算法的终止条件是两个链表都为空。当两个链表都为空时,我们返回一个空链表,这将结束递归调用。

代码实现

def mergeTwoLists(l1, l2):
    """
    合并两个升序链表

    :param l1: 第一个链表
    :param l2: 第二个链表
    :return: 合并后的链表
    """

    # 如果两个链表都为空,则返回一个空链表
    if not l1 and not l2:
        return None

    # 如果其中一个链表为空,则返回另一个链表
    if not l1:
        return l2
    if not l2:
        return l1

    # 比较两个链表的头节点的数据,较小的那个节点成为合并后链表的头节点
    if l1.val < l2.val:
        head = l1
        l1 = l1.next
    else:
        head = l2
        l2 = l2.next

    # 将较小节点的下一个节点作为合并后链表的下一个节点,然后递归地合并剩下的两个链表
    head.next = mergeTwoLists(l1, l2)

    return head

总结

[21] 合并两个有序链表是一道经典的LeetCode题目。它考察了我们对链表的基本操作、递归的思想和升序链表的理解。通过本文的讲解,希望你能对这道题有更深入的认识。