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

输入:head = [1,2,3,4] 输出:[2,1,4,3]
示例 2:
输入:head = [] 输出:[]
示例 3:
输入:head = [1] 输出:[1]
提示:
- 链表中节点的数目在范围
[0, 100]
内 0 <= Node.val <= 100
Related Topics
- 递归
- 链表
2、题目分析
两两交换(交换start、end)其实就是涉及三条指针的调整:p1->start->end->
指针1:p1->start 要调整为 p1->end
指针2:start->end 要调整为 start->
指针3:end-> 要调整为 end->start
3、复杂度最优解代码示例
// 递归写法
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
class Solution {
public ListNode swapPairs(ListNode head) {
// 边界条件:如果链表为空或只有一个节点,直接返回
if (head == null || head.next == null) return head;
// 交换当前两个节点
ListNode nextPair = head.next.next; // 保存剩余链表的头节点
ListNode newHead = head.next; // 新的头节点是第二个节点
newHead.next = head; // 第一个节点的下一个节点指向第二个节点的下一个节点
head.next = swapPairs(nextPair); // 第一个节点指向递归处理后的剩余链表
return newHead; // 返回新的头节点
}
}
// 迭代写法
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(0); // 创建一个哑节点作为新链表的头前驱
dummy.next = head;
ListNode current = dummy;
while (current.next != null && current.next.next != null) {
// 获取当前节点对的指针
ListNode first = current.next;
ListNode second = current.next.next;
// 交换节点对的位置
first.next = second.next;
second.next = first;
current.next = second;
// 更新current指针,为下一次循环做准备
current = first;
}
// 返回哑节点的下一个节点作为新链表的头
return dummy.next;
}
4、适用场景
如医院挂号排队:
想象一下你到医院看病,你和其他患者都在排队等待挂号和就诊。在这个排队过程中,可能会遇到一些情况,比如某些患者需要提前看医生,或者某些患者需要重新安排顺序等。
这个场景中的排队可以类比为一个链表,每个节点代表一个患者。"两两交换链表中的节点"问题可以类比为医院工作人员对排队患者进行两两交换位置,以便更有效地安排就诊顺序。
通过解决这个问题,医院可以优化排队顺序,让就诊更加高效。例如,可能会将每个患者与其后面的患者进行两两交换,以确保就诊顺序更加合理,减少等待时间,并提高医院的服务效率。