两两交换链表中的结点:LeetCode 24
2023-09-15 13:20:22
两两交换链表中的结点:理解和实现
在数据结构中,链表是一种广泛使用的线性数据结构,它将数据存储在相互连接的结点序列中。这些结点由一个存储元素的值以及指向下一个结点的指针组成。链表在解决各种计算问题中发挥着至关重要的作用,例如存储有序数据和高效查找。
本文将深入探讨两两交换链表中的结点 的任务,这是一个经典的链表操作问题,要求我们将链表中相邻的两个结点进行交换,直至链表末尾。我们将探索该问题的两个有效方法:递归 和迭代 ,并为每个方法提供清晰的代码实现和详细的解释。
理解问题
给定一个单链表,两两交换其中相邻的结点。例如,对于链表 [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
代码解析
- 初始化前驱结点
prev
为None
. - 遍历链表:
- 将头结点
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. 如果链表为空怎么办?
空链表不需要交换,因此返回空链表。