206. 反转链表 (Easy)
专题归类: 04-链表 LeetCode 链接: https://leetcode.cn/problems/reverse-linked-list/
在线做题: 写 Python 代码并运行 · Java 跳转 LeetCode
题目描述
给你单链表的头节点 head,请你反转链表,并返回反转后的链表。
示例:
- 输入:head = [1,2,3,4,5]
- 输出:[5,4,3,2,1]
题目详细分析
- 数据范围: 节点数在 [0, 5000] 范围内,节点值在 [-5000, 5000] 范围内
- 输入特征: 单向链表,每个节点只有一个 next 指针指向后继
- 核心约束: 反转后原链表的尾节点变成新链表的头节点,原头节点变成新链表的尾节点(next 指向 None)
- 隐藏条件: 链表的单向性意味着一旦断开 next 连接就会丢失后续节点,操作前必须先保存
- 边界条件: 空链表(head 为 None)、只有一个节点的链表
小白版直白理解
就像一串珠子用线串起来,现在要把这串珠子倒过来。你不能直接整串翻转,只能一颗一颗地拆开重新串。
具体怎么做呢?先准备好一根空线(pre = None),然后从第一颗珠子开始,每取下一颗珠子,就把它串到新线的最前面。这样取完所有珠子后,新线上珠子的顺序就是反的了。
解题思路
思路一:迭代法(三指针翻转,推荐)
为什么这样想: 反转一个节点的核心操作是 cur.next = pre,但这样会断开与后续节点的连接。所以需要一个指针 nxt 先保存后续节点。反转完当前节点后,三个指针整体后移一位,重复操作。
关键洞察: pre 始终指向「已反转部分的头节点」,cur 指向「当前待反转的节点」。每次迭代把 cur 从原链表中「摘下来」放到 pre 的前面。
def reverseList(head):
"""迭代法:三指针翻转"""
pre = None # 已反转部分的头
cur = head # 当前待反转节点
while cur:
nxt = cur.next # 先保存下一个节点,防断链
cur.next = pre # 翻转:当前节点指向前一个
pre = cur # pre 前移
cur = nxt # cur 前移
return pre # pre 就是新链表的头节点思路二:递归法
思路讲解: 递归地反转 head.next 及之后的链表,得到的新链表头节点为 new_head。此时 head.next 指向反转后的最后一个节点,只需让 head.next.next = head 将当前节点接到尾部,再让 head.next = None 断掉原连接。递归的终止条件是空或只有一个节点。
关键洞察: 递归法的核心是「相信子问题能正确反转」,我们只需要处理当前节点和已反转部分尾部的连接。
def reverseList(head):
"""递归法"""
# 终止条件:空或只有一个节点
if not head or not head.next:
return head
new_head = reverseList(head.next) # 递归反转后续链表
head.next.next = head # 将当前节点接到尾部
head.next = None # 断开原 next 指针
return new_head思路三:头插法(借助虚拟头节点)
思路讲解: 创建一个虚拟头节点 dummy,然后遍历原链表,每遍历一个节点就用头插法插入到 dummy 后面。最后返回 dummy.next。本质上和迭代法一样,但用 dummy 统一了插入逻辑。
def reverseList(head):
"""头插法"""
dummy = ListNode(0)
cur = head
while cur:
nxt = cur.next
# 头插:将 cur 插入到 dummy 后面
cur.next = dummy.next
dummy.next = cur
cur = nxt
return dummy.next易错点
- 断链问题: 执行
cur.next = pre之前,一定要先保存nxt = cur.next,否则后续节点丢失 - 递归返回值: 递归的核心是返回 new_head(即原链表尾节点),不是 head
- 尾节点处理: 反转后原头节点变成尾节点,要记得将
head.next设为 None,否则形成环 - 空链表和单节点: 这两种情况直接返回 head,反转前和反转后结果一样
- pre 初始化: pre 必须初始化为 None,因为反转后头节点的 next 指向 None
框架提炼
三指针迭代反转模板: 最基础的链表操作,几乎所有链表 Hard 题(K 个一组翻转、反转区间等)的构成基础。
pre, cur = None, head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre递归反转模板:
def reverse(head):
if not head or not head.next:
return head
new_head = reverse(head.next)
head.next.next = head
head.next = None
return new_head这两个模板必须熟练掌握,因为它们在许多进阶题目中被反复调用。
关联题目
- 92-反转链表II — 反转链表的指定区间,是本题的区间扩展
- 25-K个一组翻转链表 — 每 K 个一组翻转,Hard 难度,需要反复调用本题的反转逻辑
- 234-回文链表 — 判断回文需要先反转后半部分链表