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

// 定义链表节点类,每个节点包含一个整数值 val 和一个指向下一个节点的引用 next
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
class Solution {
/**
* 该方法用于两两交换链表中相邻的节点,并返回交换后链表的头节点
* @param head 原始链表的头节点
* @return 交换后链表的头节点
*/
public ListNode swapPairs(ListNode head) {
// 递归终止条件:如果链表为空或者链表只有一个节点,无法进行交换,直接返回原链表头节点
if (head == null || head.next == null) {
return head;
}
// 记录当前两个相邻节点中的第二个节点,交换后它将成为新的头节点
ListNode newHead = head.next;
// 递归调用 swapPairs 方法处理剩余的链表节点
// 对于当前的两个相邻节点,head 是第一个,newHead 是第二个,newHead.next 是剩余链表的头节点
// 递归处理剩余链表后,将 head 的 next 指针指向处理后的剩余链表的头节点
head.next = swapPairs(newHead.next);
// 完成当前两个相邻节点的交换,将 newHead 的 next 指针指向 head
newHead.next = head;
// 返回交换后当前这一组节点的新头节点,也就是原本的第二个节点 newHead
return newHead;
}
}

代码解释
本题要求两两交换链表中相邻的节点,并且不能修改节点内部的值,只能进行节点交换。我们可以使用迭代的方法,借助虚拟头节点来简化操作。
具体步骤
- 创建虚拟头节点 :
- 创建一个值为 0 的虚拟头节点
dummy
,其next
指针指向原链表的头节点head
。这样做是为了方便处理头节点交换的情况,避免单独处理头节点交换的特殊逻辑。
- 创建一个值为 0 的虚拟头节点
- 初始化指针 :
- 定义指针
prev
并将其初始化为虚拟头节点dummy
,prev
用于记录要交换的两个节点的前一个节点。
- 定义指针
- 循环进行节点交换 :
- 使用
while
循环,只要prev
后面至少还有两个节点(即prev.next != null && prev.next.next != null
),就继续进行交换操作。 - 在每次循环中:
- 定义
first
指向要交换的第一个节点(prev.next
),second
指向要交换的第二个节点(prev.next.next
)。 - 进行节点交换操作:
- 将
prev
的next
指针指向second
。 - 将
first
的next
指针指向second
的下一个节点。 - 将
second
的next
指针指向first
。
- 将
- 更新
prev
指针,将其指向first
,以便处理下一组要交换的节点。
- 定义
- 使用
- 返回结果 :
- 当循环结束后,返回虚拟头节点
dummy
的下一个节点,即交换后链表的头节点。
- 当循环结束后,返回虚拟头节点