【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指针准备下一轮交换。

相关推荐
幻云20101 小时前
Next.js 之道:从入门到精通
前端·javascript·vue.js·人工智能·python
SunnyDays10112 小时前
使用 Python 自动查找并高亮 Word 文档中的文本
经验分享·python·高亮word文字·查找word文档中的文字
深蓝电商API2 小时前
Selenium处理弹窗、警报和验证码识别
爬虫·python·selenium
傻啦嘿哟2 小时前
构建命令行单词记忆工具:JSON词库与复习算法的完美结合
算法·json
mjhcsp2 小时前
一种新的LCA算法
算法
wen__xvn2 小时前
代码随想录算法训练营DAY24第七章 回溯算法part03
算法·深度优先
深蓝电商API2 小时前
Selenium模拟滚动加载无限下拉页面
爬虫·python·selenium
无尽的罚坐人生2 小时前
hot 100 560.和为 K 的子数组
数据结构·算法·leetcode
Ll13045252982 小时前
leetcode代码随想录数组篇
数据结构·算法·leetcode