24. 两两交换链表中的节点

146 阅读4分钟

【题目】

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

  示例 1:

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

示例 2:

输入: head = []
输出: []

示例 3:

输入: head = [1]
输出: [1]

提示:

  • 链表中节点的数目在范围 [0, 100] 内
  • 0 <= Node.val <= 100

【题目解析】

思路:

两两交换链表中的节点是一个典型的链表操作问题,可以通过修改节点间的链接来实现。关键在于正确处理节点间的链接关系,特别是考虑到边界情况,如链表长度为奇数或链表为空。

解题思路:

  1. 创建一个哑结点:这个哑结点将作为链表头部的前一个节点,以简化边界条件处理。

  2. 遍历链表,交换节点

    • 使用三个指针:prev(指向待交换节点对的前一个节点),node1(待交换节点对的第一个节点),node2(待交换节点对的第二个节点)。
    • 在每一步中,更改 prevnext 指针,使其指向 node2,然后更改 node2next 指针,使其指向 node1。最后,调整 node1next 指针指向 node2 的原 next 节点。
    • 更新 prev 为当前节点对的第二个节点,即 node1
  3. 处理边界条件:当链表长度为奇数时,最后一个节点不需要交换。

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        # 创建一个哑结点
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy

        # 遍历链表,两两交换节点
        while prev.next and prev.next.next:
            node1 = prev.next
            node2 = node1.next
            prev.next, node1.next, node2.next = node2, node2.next, node1
            prev = node1

        return dummy.next

执行:

image.png

【总结】

适用问题类型: 两两交换链表中的节点问题属于链表操作类问题,特别是那些涉及直接修改链表节点链接的情况。这类问题通常要求不修改节点内部的值,而是通过重新排列节点本身来改变链表的结构。适用于这种方法的问题通常包括:

  • 链表的重新排序或重排。
  • 链表节点的成对交换或按特定模式交换。
  • 更复杂的链表变换操作,如链表的部分反转或重新分组。

使用的算法: 此问题使用的是一种迭代方法,结合了指针操作的技巧。算法的核心在于正确处理节点间的链接关系,以及确保在修改链表结构时不会丢失或断开任何节点。

算法细节

  1. 哑结点:引入哑结点(dummy node)作为链表的新头部,有助于简化头部交换的边界情况处理。
  2. 迭代处理:通过循环遍历链表,每次处理一对节点。使用三个指针:prev 指向待交换对的前一个节点,node1node2 分别指向待交换的两个节点。
  3. 交换节点:在每一对节点中,调整 prevnext 指针指向 node2node1next 指针指向 node2 的下一个节点,然后 node2next 指向 node1。这样完成了一对节点的交换。
  4. 更新指针:更新 prev 指针为当前对的第二个节点,为处理下一对节点做准备。

算法性能: 这个算法的时间复杂度为 O(n),其中 n 是链表中的节点数。这是因为每个节点在算法中只被访问一次。空间复杂度为 O(1),因为除了已有的链表外,只需要常数空间来存储指针。

总结与扩展: 两两交换链表中的节点问题是一个很好的练习,用于理解和熟悉链表的操作。这种类型的问题不仅考验了基本的链表知识,也需要在操作过程中保持对链表结构的清晰理解,以避免常见的错误。掌握了这种链表操作技巧,可以应用于更复杂的链表问题,如链表反转、重排链表、或者在链表中进行特定模式的数据重组。对于任何需要精确控制链表结构的问题,这些技能都是极其宝贵的。

题目链接

两两交换链表中的节点