hot 100 第三十题 30. 两两交换链表中的节点

题目

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

示例 1:

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

示例 2:

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

示例 3:

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

核心思路

迭代法:每次处理两个节点,改变它们的next指针实现交换。

复制代码
原链表: 1 → 2 → 3 → 4

交换1和2:
2 → 1 → 3 → 4

交换3和4:
2 → 1 → 4 → 3

结果: 2 → 1 → 4 → 3

题解

复制代码
class Solution {
    public ListNode swapPairs(ListNode head) {
        // 使用哑节点简化处理
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;
        
        // 至少需要两个节点才能交换
        while (prev.next != null && prev.next.next != null) {
            // 定义要交换的两个节点
            ListNode first = prev.next;
            ListNode second = prev.next.next;
            
            // 交换节点(三步)
            first.next = second.next;   // 1指向3
            second.next = first;        // 2指向1
            prev.next = second;         // prev指向2
            
            // 移动prev到下一对的前一个节点
            prev = first;
        }
        
        return dummy.next;
    }
}
```

### 详细演示
```
原链表: 1 → 2 → 3 → 4

步骤1: 创建哑节点
------------------
dummy → 1 → 2 → 3 → 4
prev↑

步骤2: 第一次交换(1和2)
------------------
定义节点:
first = 1
second = 2

交换前:
dummy → 1 → 2 → 3 → 4
prev↑  ↑   ↑
     first second

执行交换三步:

① first.next = second.next
   1 → 3

dummy → 1 → 2 → 3 → 4
        ↓       ↑
        └───────┘

② second.next = first
   2 → 1

dummy → 1 ← 2   3 → 4
        ↓   ↑
        └───┘

③ prev.next = second
   dummy → 2

dummy → 2 → 1 → 3 → 4
        ↑   ↓   ↑
        └───┴───┘

交换完成:
dummy → 2 → 1 → 3 → 4

移动prev:
prev = first (现在first是节点1)

dummy → 2 → 1 → 3 → 4
            prev↑

步骤3: 第二次交换(3和4)
------------------
定义节点:
first = 3
second = 4

交换前:
dummy → 2 → 1 → 3 → 4
            prev↑ ↑   ↑
                 first second

执行交换:
① first.next = second.next
   3 → null

② second.next = first
   4 → 3

③ prev.next = second
   1 → 4

结果:
dummy → 2 → 1 → 4 → 3 → null

移动prev:
prev = first (节点3)

步骤4: 检查循环条件
------------------
prev.next = 3
prev.next.next = null

条件不满足,循环结束

返回 dummy.next
最终: 2 → 1 → 4 → 3
```

## 交换的三步详解

这是最关键的部分,顺序不能错:
```
交换前:
prev → first → second → next
  ↑      ↑       ↑       ↑
dummy    1       2       3

目标:
prev → second → first → next
  ↑      ↑       ↑       ↑
dummy    2       1       3

三步:
------------------
步骤1: first.next = second.next
让1指向3(跳过2)

prev → first   second → next
        ↓   ╲    ↑       ↑
        └────╲───┘       │
              ╲__________│

步骤2: second.next = first
让2指向1

prev → first ← second → next
        ↓              ↗
        └──────────────┘

步骤3: prev.next = second
让prev指向2

prev ──→ second → first → next
           ↑       ↑       ↑
           2       1       3

完成!
```

## 图解交换过程
```
原始状态:
dummy → 1 → 2 → 3 → 4
        ↑   ↑
      first second

目标状态:
dummy → 2 → 1 → 3 → 4
        ↑   ↑
     second first

改变指针方向:
1. 1.next = 3     (1跳过2)
2. 2.next = 1     (2指回1)
3. dummy.next = 2 (dummy指向2)

本质

两两交换链表节点体现了:

  1. 指针作 --- 改变next指针实现节点重排
  2. 固定的交换步骤 --- 三步法完成交换
  3. 哑节点技巧 --- 统一处理头节点

关键是理解交换的三步顺序

  1. first.next = second.next(保存后续)
  2. second.next = first(交换)
  3. 上一页下一页 = second(连接)
相关推荐
仟濹4 分钟前
【算法打卡day34(2026-03-30 周一)】DFS专项训练(今日算法:DFS & 记忆化搜索 & 回溯)
算法·深度优先
罗湖老棍子8 分钟前
【 例 1】区间和(信息学奥赛一本通- P1547)(基础线段树和单点修改区间查询树状数组模版)
数据结构·算法·线段树·树状数组·单点修改 区间查询
Book思议-24 分钟前
【数据结构】栈与队列核心对比
数据结构·栈与队列对比
旺仔.29128 分钟前
常用算法 详解
数据结构·算法
今儿敲了吗32 分钟前
算法复盘——差分
数据结构·c++·笔记·学习·算法
qq_3985865442 分钟前
平衡三进制超前进位加法器
算法
西西弟1 小时前
最短路径之Dijkstra算法(数据结构)
数据结构·算法
沉鱼.441 小时前
树形DP题目
算法·深度优先
VelinX1 小时前
【个人学习||算法】多维动态规划
学习·算法·动态规划
AlenTech1 小时前
139. 单词拆分 - 力扣(LeetCode)
算法·leetcode·职场和发展