返回

两两交换链表中的结点:LeetCode 24

前端

两两交换链表中的结点:理解和实现

在数据结构中,链表是一种广泛使用的线性数据结构,它将数据存储在相互连接的结点序列中。这些结点由一个存储元素的值以及指向下一个结点的指针组成。链表在解决各种计算问题中发挥着至关重要的作用,例如存储有序数据和高效查找。

本文将深入探讨两两交换链表中的结点 的任务,这是一个经典的链表操作问题,要求我们将链表中相邻的两个结点进行交换,直至链表末尾。我们将探索该问题的两个有效方法:递归迭代 ,并为每个方法提供清晰的代码实现和详细的解释。

理解问题

给定一个单链表,两两交换其中相邻的结点。例如,对于链表 [1, 2, 3, 4, 5, 6],交换后的链表应为 [2, 1, 4, 3, 6, 5].

递归方法

递归是一种强大且优雅的问题解决技术,它通过不断将问题分解成更小的子问题来求解。

代码实现

def pairwise_swap_recursive(head):
    """
    递归交换链表中相邻的结点。

    参数:
    head: 链表头结点

    返回:
    交换后的链表头结点
    """

    # 基本情况:空链表或只有一个结点
    if not head or not head.next:
        return head

    # 交换头结点和下一个结点
    first, second = head, head.next
    first.next = pairwise_swap_recursive(second.next)
    second.next = first

    return second

代码解析

  • 递归基例:如果链表为空或只有一个结点,则返回头结点,表示没有结点需要交换。
  • 递归步骤:
    • 将头结点 head 和下一个结点 second 交换。
    • head 的下一个指针指向递归调用以交换 second.next 后返回的子链表。
    • second 的下一个指针指向交换后的 head

迭代方法

迭代是一种逐个遍历数据结构并逐步修改它的技术。

代码实现

def pairwise_swap_iterative(head):
    """
    迭代交换链表中相邻的结点。

    参数:
    head: 链表头结点

    返回:
    交换后的链表头结点
    """

    # 记录前驱结点,用于连接交换后的结点
    prev = None

    # 遍历链表
    while head and head.next:
        # 交换头结点和下一个结点
        first, second = head, head.next
        if prev:
            prev.next = second
        prev = first
        first.next = second.next
        second.next = first
        head = second

    return head

代码解析

  • 初始化前驱结点 prevNone.
  • 遍历链表:
    • 将头结点 head 和下一个结点 second 交换。
    • 如果 prev 不为空,将 prev.next 指向交换后的 second.
    • prev 更新为交换后的 first.
    • first 的下一个指针指向交换后的 second.
    • second 的下一个指针指向交换后的 first.
    • head 更新为交换后的 second.

时间复杂度

两种方法的时间复杂度都是 O(n),其中 n 是链表的长度。

实例

示例 1:

  • 输入:[1, 2, 3, 4, 5, 6]
  • 输出:[2, 1, 4, 3, 6, 5]

示例 2:

  • 输入:[]
  • 输出:[]

示例 3:

  • 输入:[1]
  • 输出:[1]

总结

两两交换链表中的结点是一种常见且重要的链表操作任务,可以通过递归或迭代方法高效解决。本文详细介绍了这两种方法,提供了清晰的代码实现和详细的解释。对于不同的需求和偏好,选择最合适的方法至关重要。

常见问题解答

1. 交换链表结点有什么实际应用?
交换链表结点是一种常见技术,用于解决各种问题,例如链表反转、环检测和链表排序。

2. 递归方法和迭代方法哪个更好?
这取决于具体情况。递归方法更简洁优雅,但可能会导致堆栈溢出。迭代方法更直接,易于理解,但可能在处理长链表时效率较低。

3. 是否有其他交换链表结点的方法?
除了递归和迭代方法外,还可以使用诸如双指针或反向指针之类的其他方法。

4. 如果链表长度为奇数,怎么处理?
奇数长度的链表中最后一个结点不会交换,因为它没有下一个结点。

5. 如果链表为空怎么办?
空链表不需要交换,因此返回空链表。