1. 题目到底在考什么:先看懂这道题的核心意图
力扣第24题“两两交换链表中的节点”是一道非常经典的链表操作题,难度标的是Medium,但说实话,它的代码量不大,真正难的是指针操作的顺序和边界条件的处理。题目要求很明确:给定一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。而且题目特别强调,不能只是修改节点内部的值,必须真的把节点交换掉。
这道题为什么值得反复刷?因为它几乎是链表题里“指针操作基本功”的试金石。你如果能把这道题的迭代法和递归法都写明白、讲清楚,那链表相关的很多题(反转链表、K个一组反转、重排链表)基本就通了一大半。
我从自己刷题的经历来看,这道题最典型的“坑”有这几个:交换完之后指针绕不回来、head变化之后返回值搞错、链表长度是奇数时尾巴怎么处理。每个坑都对应一个核心知识点,下面我一个个拆开讲。
提示:如果你完全没接触过链表,先用5分钟搞明白单链表的结构——每个节点有一个value和一个next指针,链表的头节点是入口,遍历靠next一个一个往下走。这道题基于的就是这个最基础的结构。
在进入正题之前,先看一眼题目给的链表节点定义,后面所有代码都基于这个结构:
python复制# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
接下来我们分两条路线来啃这道题:迭代法(虚拟头节点)和递归法。两种写法都要会,因为面试官非常喜欢让你“再写一种方法”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解法一:迭代法,虚拟头节点是链表题的万能钥匙
2.1 为什么一上来就要用虚拟头节点
迭代法最让人头疼的地方在于:头节点会变。题目要求把第一个节点和第二个节点交换,交换完之后,原来链表的head变成了第二个节点。如果你按常规方法直接操作原head,最后返回值就会很麻烦,要么额外用一个变量记录新head,要么单独处理头节点的特殊情况。
虚拟头节点(dummy node)就是为了解决这个问题出现的。它的思路很简单:在真正的头节点前面再挂一个新的节点,这个节点本身不存有效数据,只是让“头节点的变化”变成一个普通操作,最后返回dummy.next就行。
python复制class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy = ListNode(0) # 虚拟头节点
dummy.next = head
prev = dummy # prev始终指向“已经处理完的链表的尾部”
while prev.next and prev.next.next:
node1 = prev.next
node2 = node1.next
# 核心交换逻辑
prev.next = node2
node1.next = node2.next
node2.next = node1
# 移动prev到下一组的前驱位置
prev = node1
return dummy.next
这段代码看起来简单,但我第一次写的时候还是绕了半天。关键就三行交换逻辑,我建议你用笔画一下指针变化,比盯着代码看有效得多。
2.2 三行交换逻辑,每一行的顺序都不能错
我们假设当前状态是:prev -> node1 -> node2 -> nextNode,目标是把node1和node2交换,变成prev -> node2 -> node1 -> nextNode。
第一步:prev.next = node2,让prev先指向node2。这一步把node2从后面“提”到了前面。
第二步:node1.next = node2.next,让node1指向node2原来的下一个节点(也就是nextNode)。这一步必须做,否则node1和node2会互相指着,形成环。
第三步:node2.next = node1,让node2指回node1,完成这两个节点的交换。
然后prev = node1,因为交换完之后,node1已经成了这一组的尾部,下一组要交换的节点是从node1.next开始的。
**交换顺序为什么不
