
LeetCode 24. 两两交换链表中的节点链表操作的经典应用问题描述给你一个链表两两交换其中相邻的节点并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题即只能进行节点交换。示例 1输入head [1,2,3,4] 输出[2,1,4,3]示例 2输入head [] 输出[]示例 3输入head [1] 输出[1]算法原理核心思路两两交换链表中的节点问题可以通过以下方法解决递归方法递归地交换前两个节点然后将剩余的链表递归处理。基本情况如果链表为空或只有一个节点直接返回该链表。迭代方法使用一个哑节点作为头节点的前一个节点。遍历链表每次交换两个相邻的节点。复杂度分析递归方法时间复杂度O(n)其中 n 是链表的长度。每个节点恰好被访问一次。空间复杂度O(n)递归调用栈的深度为 n/2。迭代方法时间复杂度O(n)其中 n 是链表的长度。每个节点恰好被访问一次。空间复杂度O(1)只需要常数级别的额外空间。代码实现递归方法# Definition for singly-linked list. class ListNode: def __init__(self, val0, nextNone): self.val val self.next next class Solution: def swapPairs(self, head: Optional[ListNode]) - Optional[ListNode]: # 基本情况如果链表为空或只有一个节点直接返回 if not head or not head.next: return head # 保存第二个节点 second head.next # 递归处理剩余的链表 head.next self.swapPairs(second.next) # 交换前两个节点 second.next head # 返回新的头节点 return second迭代方法# Definition for singly-linked list. class ListNode: def __init__(self, val0, nextNone): self.val val self.next next class Solution: def swapPairs(self, head: Optional[ListNode]) - Optional[ListNode]: # 创建哑节点方便处理头节点的情况 dummy ListNode(0, head) prev dummy # 遍历链表每次交换两个相邻的节点 while prev.next and prev.next.next: # 保存第一个节点 first prev.next # 保存第二个节点 second prev.next.next # 交换节点 first.next second.next second.next first prev.next second # 移动 prev 指针 prev first # 返回新的头节点 return dummy.next代码解析递归方法基本情况如果链表为空或只有一个节点直接返回该链表。保存第二个节点保存第二个节点因为它将成为新的头节点。递归处理递归处理剩余的链表将结果连接到第一个节点的后面。交换节点将第二个节点的 next 指针指向第一个节点。返回结果返回新的头节点即第二个节点。迭代方法创建哑节点创建一个哑节点指向头节点方便处理头节点的情况。初始化指针prev指针指向哑节点。遍历链表每次处理两个相邻的节点。交换节点保存第一个节点first和第二个节点second。将first的 next 指针指向second的 next。将second的 next 指针指向first。将prev的 next 指针指向second。移动指针将prev指针移动到first准备处理下一对节点。返回结果返回哑节点的 next 指针即新的头节点。实战技巧递归方法递归终止条件当链表为空或只有一个节点时直接返回。指针操作正确处理节点之间的指针关系确保链表不会断裂。迭代方法哑节点使用哑节点可以避免处理头节点的特殊情况。指针管理在交换节点时需要仔细管理各个指针的指向确保链表的完整性。错误分析常见错误边界条件处理错误没有处理链表为空或只有一个节点的情况。指针操作错误在交换节点时指针操作顺序错误导致链表断裂。递归终止条件错误递归终止条件设置错误导致无限递归。扩展思考变种问题K 个一组翻转链表每 K 个节点一组进行翻转。反转链表反转整个链表。部分反转链表反转链表的一部分。应用场景两两交换链表中的节点问题在以下场景中有着广泛的应用链表操作练习链表的节点交换操作。算法设计递归和迭代的结合应用。数据处理处理需要两两交换元素的场景。个人实践感悟最近在准备转正答辩每天被各种算法题和合并冲突吓醒救命今天刷到这个经典的两两交换链表中的节点问题突然想到刚实习时第一次写这个题的场景。当时我还不知道使用递归直接用了迭代结果指针操作错误导致链表断裂被mentor嘲笑了一整天麻了现在再看这个问题其实递归方法非常简洁。通过递归处理剩余的链表然后交换前两个节点代码非常清晰。这让我意识到算法的学习真的是一个循序渐进的过程从一无所知到熟练掌握需要不断地练习和总结。最后分享一个小技巧在面试中遇到链表交换问题首先要想到递归和迭代两种方法。递归方法代码简洁迭代方法空间复杂度更低。根据具体情况选择合适的方法。这就是大佬吗我也要成为这样的人输入输出示例输入输出示例 1输入head [1,2,3,4]输出[2,1,4,3]输入输出示例 2输入head []输出[]输入输出示例 3输入head [1]输出[1]结语两两交换链表中的节点问题是链表算法中的经典问题掌握它不仅有助于解决相关的LeetCode问题也能帮助我们更好地理解链表的操作和递归的应用。希望这篇文章对大家有所帮助祝大家刷题愉快