【LeetCode刷题】两两交换链表中的节点

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

示例 1:

复制代码
输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

复制代码
输入:head = []
输出:[]

示例 3:

复制代码
输入:head = [1]
输出:[1]

提示:

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

思路解析

  1. 虚拟头节点 :创建 dummy 节点并让它指向原链表头,这样可以统一处理头节点和后续节点的交换逻辑,避免头节点特殊处理。
  2. 迭代交换 :用 prev 指针跟踪当前交换组的前一个节点,每次循环处理 prev.nextprev.next.next 两个节点:
    • 先保存两个节点的引用 node1node2
    • 调整指针完成交换:让 prev 指向 node2node1 指向 node2 的下一个节点,node2 指向 node1
    • 移动 prevnode1,准备处理下一组节点。
  3. 终止条件 :当 prev.nextprev.next.next 为空时,说明没有更多可交换的节点,结束循环。
  4. 返回结果 :最终返回 dummy.next,即交换后的新链表头。

示例验证

对于输入 head = [1,2,3,4]

  • 初始 dummy -> 1 -> 2 -> 3 -> 4
  • 第一次交换后:dummy -> 2 -> 1 -> 3 -> 4prev 移动到 1
  • 第二次交换后:dummy -> 2 -> 1 -> 4 -> 3prev 移动到 3
  • 循环结束,返回 dummy.next2 -> 1 -> 4 -> 3,与示例输出一致。

Python代码

python 复制代码
from typing import Optional, List


# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 虚拟头节点,统一处理头节点交换(避免头节点特殊逻辑)
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy  # 指向当前交换组的前一个节点

        # 循环条件:至少有两个节点可交换
        while prev.next and prev.next.next:
            # 取出当前要交换的两个节点
            node1 = prev.next  # 第一个待交换节点
            node2 = prev.next.next  # 第二个待交换节点

            # 核心:调整指针完成两两交换
            prev.next = node2  # 前一个节点指向第二个节点(交换后第一个节点)
            node1.next = node2.next  # 第一个节点指向第二个节点的下一个节点
            node2.next = node1  # 第二个节点指向第一个节点

            # 移动指针到下一组的前一个节点(即当前交换后的第二个节点)
            prev = node1

        # 返回交换后的链表头(虚拟头节点的下一个节点)
        return dummy.next


# 辅助函数1:从列表创建链表(方便测试)
def create_linked_list(nums: List[int]) -> Optional[ListNode]:
    if not nums:
        return None
    head = ListNode(nums[0])
    current = head
    for num in nums[1:]:
        current.next = ListNode(num)
        current = current.next
    return head


# 辅助函数2:打印链表(直观查看结果)
def print_linked_list(head: Optional[ListNode]) -> None:
    current = head
    result = []
    while current:
        result.append(str(current.val))
        current = current.next
    print(" -> ".join(result) if result else "空链表")


# 测试用例(覆盖常见场景)
if __name__ == "__main__":
    solution = Solution()

    # 测试用例1:偶数个节点 [1,2,3,4] → 预期 [2,1,4,3]
    test1 = create_linked_list([1, 2, 3, 4])
    print("测试用例1 原链表:", end="")
    print_linked_list(test1)
    res1 = solution.swapPairs(test1)
    print("测试用例1 交换后:", end="")
    print_linked_list(res1)

    # 测试用例2:奇数个节点 [1,2,3] → 预期 [2,1,3]
    test2 = create_linked_list([1, 2, 3])
    print("\n测试用例2 原链表:", end="")
    print_linked_list(test2)
    res2 = solution.swapPairs(test2)
    print("测试用例2 交换后:", end="")
    print_linked_list(res2)

    # 测试用例3:空链表 → 预期 空链表
    test3 = create_linked_list([])
    print("\n测试用例3 原链表:", end="")
    print_linked_list(test3)
    res3 = solution.swapPairs(test3)
    print("测试用例3 交换后:", end="")
    print_linked_list(res3)

    # 测试用例4:单个节点 [1] → 预期 [1]
    test4 = create_linked_list([1])
    print("\n测试用例4 原链表:", end="")
    print_linked_list(test4)
    res4 = solution.swapPairs(test4)
    print("测试用例4 交换后:", end="")
    print_linked_list(res4)

LeetCode提交代码

python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 虚拟头节点,统一处理头节点交换
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy
        
        while prev.next and prev.next.next:
            # 取出当前要交换的两个节点
            node1 = prev.next
            node2 = prev.next.next
            
            # 交换节点
            prev.next = node2
            node1.next = node2.next
            node2.next = node1
            
            # 移动指针到下一组的前一个节点
            prev = node1
        
        return dummy.next

程序运行结果展示

测试用例1 原链表:1 -> 2 -> 3 -> 4

测试用例1 交换后:2 -> 1 -> 4 -> 3

测试用例2 原链表:1 -> 2 -> 3

测试用例2 交换后:2 -> 1 -> 3

测试用例3 原链表:空链表

测试用例3 交换后:空链表

测试用例4 原链表:1

测试用例4 交换后:1

总结

本文介绍了如何通过迭代方法实现链表相邻节点的两两交换。通过创建虚拟头节点(dummy)统一处理头节点交换,使用prev指针跟踪交换组前驱节点,每次循环交换prev.next和prev.next.next两个节点。算法时间复杂度O(n),空间复杂度O(1)。代码实现包含链表创建、打印等辅助函数,并测试了偶数节点、奇数节点、空链表和单节点等典型情况,验证了算法的正确性。关键步骤包括保存节点引用、调整指针顺序完成交换,以及移动prev指针准备下一轮交换。

相关推荐
北域码匠1 小时前
高通滤波算法深度解析(High-Pass Filter)
stm32·算法·c#·数字信号处理·嵌入式开发·滤波算法·高通滤波
问天_观心1 小时前
大模型微调学习(二)
人工智能·python·深度学习·学习·语言模型·transformer
洋洋不叫杨杨1 小时前
揭秘当下知名的SEO优化渠道,你知道几个?
大数据·python
阿童木写作2 小时前
跨境图片翻译工具推荐:批量处理视频字幕与智能抠图
python·音视频
指掀涛澜天下惊2 小时前
强化学习进阶篇八 策略梯度算法
深度学习·学习·算法·强化学习
乌萨奇也要立志学C++2 小时前
【洛谷】kmp算法
开发语言·算法
梦想的颜色2 小时前
OCR 识别原理与 Python 识图全实战:从文字提取到图像内容理解
python·计算机视觉·ocr·图像识别·python 识图
禹凕2 小时前
Dijkstra算法详解与应用
python·算法
别走!万哥爱你3 小时前
Python 中可以用于在已排序的列表中查找特定元素的位置的是什么?
python
YaraMemo3 小时前
元启发式算法框架
人工智能·算法·5g·信息与通信·启发式算法·信号处理