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(连接)
相关推荐
Hello.Reader7 小时前
算法基础(十)——分治思想把大问题拆成小问题
java·开发语言·算法
绛橘色的日落(。・∀・)ノ7 小时前
机器学习之评估与偏差方差分析
算法
消失的旧时光-19438 小时前
C语言对象模型系列(四)《Linux 内核里的 container_of 到底是什么黑魔法?》—— 一篇讲透 Linux 内核的“对象模型”核心技巧
linux·c语言·算法
AI_Ming8 小时前
从0开始学AI:层归一化,原来是这回事!
算法·ai编程
WL_Aurora8 小时前
备战蓝桥杯国赛【Day 8】
算法·蓝桥杯
智者知已应修善业9 小时前
【51单片机模拟生日蜡烛】2023-10-10
c++·经验分享·笔记·算法·51单片机
MediaTea9 小时前
Scikit-learn:从数据到结构——无监督学习的最小闭环
人工智能·学习·算法·机器学习·scikit-learn
智者知已应修善业9 小时前
【51单片机如何让LED灯从一亮到八,再从八亮到一】2023-10-13
c++·经验分享·笔记·算法·51单片机
qeen879 小时前
【数据结构】二叉树相关经典函数C语言实现
c语言·数据结构·c++·笔记·学习·算法·二叉树
良木生香9 小时前
【C++初阶】STL——List从入门到应用完全指南(1)
开发语言·数据结构·c++·程序人生·算法·蓝桥杯·学习方法