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(连接)
相关推荐
xlp666hub1 天前
Leetcode第一题:用C++解决两数之和问题
c++·leetcode
ZhengEnCi1 天前
08c. 检索算法与策略-混合检索
后端·python·算法
程序员小崔日记1 天前
大三备战考研 + 找实习:我整理了 20 道必会的时间复杂度题(建议收藏)
算法·408·计算机考研
任沫1 天前
字符串
数据结构·后端
lizhongxuan1 天前
AI小镇 - 涌现
算法·架构
AI工程架构师2 天前
通常说算力是多少 FLOPS,怎么理解,GPU和CPU为什么差异这么大
算法
祈安_2 天前
Java实现循环队列、栈实现队列、队列实现栈
java·数据结构·算法
归去_来兮2 天前
拉格朗日插值算法原理及简单示例
算法·数据分析·拉格朗日插值
千寻girling2 天前
Python 是用来做 AI 人工智能 的 , 不适合开发 Web 网站 | 《Web框架》
人工智能·后端·算法
颜酱2 天前
一步步实现字符串计算器:从「转整数」到「带括号与优化」
javascript·后端·算法