反转链表。
未标记
考查重点:指针反向与后继保留。保存 next,令当前 next 指前驱,再前移前驱/当前;迭代到空返回前驱,O(n)/O(1)
本题目录
参考答案
核心回答
反转单链表,就是原地改变每个节点的 next 指向,再返回原尾节点作为新头。 用 prev 保存已反转部分的头,curr 指向待处理节点;每轮先保存原后继,再把 curr.next 指向 prev,最后推进指针。
结束时 curr=None,prev 就是新头。每个节点处理一次,时间 O(n);迭代写法额外空间 O(1),不需要新建节点或交换节点值。
迭代实现:先保住后继,再改方向
下面假设输入是以 None 结尾的普通无环单链表,使用 Python:
class ListNode:
def __init__(self, val: int, next=None):
self.val = val
self.next = next
def reverse_list(head):
prev = None
curr = head
while curr is not None:
following = curr.next
curr.next = prev
prev = curr
curr = following
return prev
保存 following 的时机最关键。修改 curr.next 后,原来的向后连接已被覆盖;没事先保存后继,就无法沿原链表继续遍历。
以 1 → 2 → 3 → None 为例:
- 保存节点
2,令1.next=None,已反转部分为1 → None。 - 保存节点
3,令2.next=1,已反转部分为2 → 1 → None。 - 保存
None,令3.next=2;随后curr=None,返回节点3。
始终是同一批节点,改变的是连接关系。单纯倒转节点值或复制新链表,也许得到相同值序列,却没有完成原地指针反转。
为什么不会丢节点
每轮开始时,prev 指向已反转前缀,curr 指向未处理后缀。保存后继后反转当前连接,再把当前节点并入前缀,就维持了这两个部分的边界。
空链表不进循环,返回 None;单节点处理一次后返回它自身,尾部仍指向 None。重复值也按节点连接处理,不按值查找或去重。
有环输入不满足这个前提,应先确认是否需要检测和处理环,不能把普通反转代码当作任意链表结构的修复方法。
递归也能写,但调用栈不是常数空间
先反转从第二个节点开始的子链表,再把当前节点接到它末尾:
def reverse_recursive(head):
if head is None or head.next is None:
return head
new_head = reverse_recursive(head.next)
head.next.next = head
head.next = None
return new_head
子问题把 2 → 3 变成 3 → 2 后,head.next 仍指向节点 2。令 2.next=1,再令 1.next=None,得到完整结果。最后断开旧连接很重要,否则会保留 1 → 2 → 1 的环。
递归时间仍为 O(n),调用栈深度为 O(n)。深链还可能超过 Python 解释器的递归深度限制,因此长链表优先用迭代版本。调高 sys.setrecursionlimit() 不会改变 O(n) 栈空间,限制设得过高还可能导致解释器崩溃。
怎样检查实现
除了返回的值序列,还应检查返回原尾节点、所有原节点恰好出现一次、原头成为尾且 next=None。这能发现只倒转值、遗漏节点或制造环的问题。
再反转一次应恢复原节点顺序。边界包括空链表、单节点、两个节点和值全相同的链表;后者避免错误实现靠不同节点值蒙混过关。
参考资料
- 国内:代码随想录:反转链表:借鉴先保存后继、再改连接和推进指针的解释,核对迭代实现不丢节点的条件。
- 国内:labuladong:单链表的花式反转方法汇总:用于说明递归返回新头的含义,以及回溯时反接当前节点并断开旧连接的原因。
- 国内:Hello 算法:链表:根据节点值与后继引用的区别,解释反转连接不等于倒转节点值,以及尾节点应指向空引用。
- 国内:Doocs:反转链表:对照迭代和递归两类实现,核对空链表、单节点与递归终止条件。
- 国外:Python:sys.setrecursionlimit:核对递归深度受解释器栈限制的条件,解释为什么不靠调高限制来替代长链表的迭代实现。
- 国外:C++ 工作草案:forward_list 的操作:参考反转保持元素引用有效、时间为线性的约定,说明检查结果时还要关注原节点身份。
相关面经
6 篇网易云音乐
全栈开发 / 后端开发实习反转链表(只写实现)
小红书
给定链表头节点head,反转链表并返回新头节点,说一下思路并写代码
美团
后端开发工程师反转链表
虾皮
Agent 开发工程师手撕代码:反转单链表,并说明时间复杂度和空间复杂度。
滴滴
AI Agent 后端开发手撕代码:反转链表
展开剩余 1 篇面经
快手
反转链表。

