反转链表图文详解:从迭代到递归,小白也能懂的迭代与递归
结尾会加上一个最近热门的claude code新项目,对游戏开发感兴趣的千万不能错过。方法时间复杂度空间复杂度优点缺点迭代法O(n)O(1)空间省,效率高,易理解代码稍多一点点递归法O(n)O(n)代码极简,思路优雅空间开销大,链表太长可能栈溢出如果只是单纯做题或实际开发,迭代法是首选,既快又省空间。如果想锻炼递归思维,或者面试时展示多种解法,递归法是非常好的补充。
最后会附上claude code的一个非常特别的项目(对游戏开发感兴趣的一定不能错过)
一、前言:链表与反转是什么?
在开始解题之前,我们先来简单复习一下链表。
链表 就像一列火车,每节车厢就是一个 节点(ListNode)。每个节点有两个部分:
-
val:车厢里装的货物(数据) -
next:连接下一节车厢的挂钩(指针)
一个典型的链表长这样:
text
[ 1 | next ] → [ 2 | next ] → [ 3 | next ] → null
最后一个节点的 next 指向 null,表示火车结束了。
反转链表 就是把火车的挂钩全部反过来挂,让车头变车尾,车尾变车头:
text
反转前:1 → 2 → 3 → null
反转后:3 → 2 → 1 → null

LeetCode 206 题就是要求我们实现这个功能。而反转链表是很多链表题的基础,需要牢牢掌握。下面我会用两种方法来解决它:迭代法(双指针) 和 递归法。我们边画边讲,保证你一定能看懂!
二、方法一:迭代法(双指针)
2.1 核心思路
想象你在铁轨上,想把火车的挂钩全部反过来。你一次只能操作两个相邻的车厢,你需要一个帮手帮你记住下一节车厢是谁。
用到的工具(变量):
-
prev:指向已经反转好的那部分链表的头(最开始它是空的,因为还没反转) -
curr:指向当前正在处理的车厢(最开始是车头head) -
nextTemp:暂时记住下一节车厢,防止丢车
操作流程:
-
记下当前车厢的下一节:
nextTemp = curr.next -
把当前车厢的挂钩从指向下一节,改为指向前一节:
curr.next = prev -
把
prev和curr都往后挪一节,准备处理下一节车厢
如此循环,直到没有车厢可处理为止。
2.2 图解模拟(以 1 → 2 → 3 → null 为例)
初始状态:
text
prev = null
curr = 1
链表:1 → 2 → 3 → null
第一轮循环:
-
记下
nextTemp = 2 -
把 1 的挂钩指向
prev(null),变成:1 → null -
prev移到 1,curr移到 2
text
现在:
prev = 1 → null
curr = 2 → 3 → null
nextTemp 已完成使命(只用来临时存一下)
第二轮循环:
-
记下
nextTemp = 3 -
把 2 的挂钩指向
prev(1),变成:2 → 1 → null -
prev移到 2,curr移到 3
text
现在:
prev = 2 → 1 → null
curr = 3 → null
第三轮循环:
-
记下
nextTemp = null -
把 3 的挂钩指向
prev(2),变成:3 → 2 → 1 → null -
prev移到 3,curr移到 null
text
现在:
prev = 3 → 2 → 1 → null
curr = null
循环结束条件 curr == null 满足,退出循环。此时 prev 指向的正是反转后的新链表头节点 3。
2.3 Java 代码实现
java
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null; // 前驱节点,初始为空
ListNode curr = head; // 当前节点
while (curr != null) {
ListNode nextTemp = curr.next; // 1. 暂存下一个节点
curr.next = prev; // 2. 反转:当前节点指向前驱
prev = curr; // 3. prev 后移
curr = nextTemp; // 4. curr 后移
}
return prev; // prev 就是新链表的头节点
}
}
复杂度分析:
-
时间复杂度:O(n) —— 每个节点只访问一次
-
空间复杂度:O(1) —— 只用了三个临时指针,不随链表长度变化
三、方法二:递归法
3.1 核心思路
递归法听起来很玄乎,其实就是函数自己调用自己。我们换个角度思考:如果我能够把除了第一个节点以外的后面部分先反转好,然后再把第一个节点挂到反转部分的末尾,不就完成了吗?
这个思路就是递归的分治思想:
-
递:不断地把问题拆小,直到只剩下最后一个节点(或空链表)。
-
归:从最后一个节点开始,一步步往回拼接,把指针方向掉个头。
3.2 图解模拟(同样以 1 → 2 → 3 → null 为例)
我们用一张“调用栈”的图来跟踪(这里用文字模拟堆栈效果):
text
【递推阶段】
reverseList(1) 调用 reverseList(2)
reverseList(2) 调用 reverseList(3)
reverseList(3) 发现 head.next == null,直接返回 3
调用栈:
reverseList(1) 等待...
reverseList(2) 等待...
reverseList(3) 返回 3
回溯阶段:
-
处理节点 2(此时
head = 2)-
拿到
newHead = 3 -
让
head.next.next = head→ 即3.next = 2,链表变成3 → 2 → null -
让
head.next = null→ 切断 2 原来的指向,防止成环 -
返回
newHead(3)
-
-
处理节点 1(此时
head = 1)-
拿到
newHead = 3 -
让
head.next.next = head→ 即2.next = 1,链表变成3 → 2 → 1 → null -
让
head.next = null→ 切断 1 原来的指向 -
返回
newHead(3)
-
最终得到 3 → 2 → 1 → null。
3.3 递归的关键点解释(新手必看)
-
终止条件:
if (head == null || head.next == null) return head;
这个条件有两个作用:一是处理空链表,二是当递归到最后一个节点时返回它(它就是反转后的头节点)。 -
head.next.next = head这句到底干了啥?
假设当前head是节点 A,head.next是节点 B。原本是A → B。head.next.next就是B.next。
执行B.next = A,就变成了A ← B,实现了反向连接。 -
head.next = null为什么必须写?
如果不切断原来的指针,比如节点 2 的next还指向 3,而 3 的next又被改成了 2,就会形成2 ⇄ 3的环,导致死循环。
3.4 Java 代码实现(极其简短,但是空间占用较大,推荐锻炼思维使用)
java
class Solution {
public ListNode reverseList(ListNode head) {
// 递归终止条件:空链表或只有一个节点
if (head == null || head.next == null) {
return head;
}
// 递归反转后续部分,得到新链表的头节点(原链表的尾节点)
ListNode newHead = reverseList(head.next);
// 回溯阶段:将当前节点的下一个节点指向当前节点,完成局部反转
head.next.next = head;
head.next = null; // 切断原指针,防止成环
return newHead; // 新头节点一路返回,始终不变
}
}
复杂度分析:
-
时间复杂度:O(n) —— 每个节点访问一次
-
空间复杂度:O(n) —— 递归调用栈的深度为链表长度 n
四、两种方法对比总结
| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| 迭代法 | O(n) | O(1) | 空间省,效率高,易理解 | 代码稍多一点点 |
| 递归法 | O(n) | O(n) | 代码极简,思路优雅 | 空间开销大,链表太长可能栈溢出 |
建议:
-
如果只是单纯做题或实际开发,迭代法是首选,既快又省空间。
-
如果想锻炼递归思维,或者面试时展示多种解法,递归法是非常好的补充。
五、一个非常特别的项目——Claude-Code-Game-Studios

这个项目支持的引擎有
| Engine | Lead Agent | Sub-Specialists |
|---|---|---|
| Godot 4 | godot-specialist |
GDScript, Shaders, GDExtension |
| Unity | unity-specialist |
DOTS/ECS, Shaders/VFX, Addressables, UI Toolkit |
| Unreal Engine 5 | unreal-specialist |
GAS, Blueprints, Replication, UMG/CommonUI |
这三种。且有如此多的angent,几乎覆盖了游戏开发领域的大部分角色,非常适合独立开发者和小型团队使用。

注意:游戏开发有一定门槛,这个项目也不能完全替代现实的这些代理人,但只有熟练使用是可以大大提升这方面的能力的,让独立开发者一人成军。
具体使用方法和简介请参考其仓库:https://github.com/Donchitos/Claude-Code-Game-Studios.git
更多推荐


所有评论(0)