反转链表
在 LeetCode 上查看 ↗语音讲解
开车或通勤时可听,跟着思路走一遍
速度
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
模拟答题者思考
1. 直观想法:我需要把每个节点的 next 指针反过来指向前一个节点。
2. 关键问题:改了 cur.next 之后,我就找不到原来的下一个节点了——所以在改之前必须用 nxt 保存。
3. 初始状态:第 0 个位置是 null(pre = None),第 1 个是 head(cur = head)。
4. 循环结束后 pre 就指向了新的头节点(原链表的尾)。
变量语义(先读这三句再编码)
| 变量 | 类型 | 语义(三句法) |
|---|---|---|
pre | ListNode* | 定义:已反转部分的头节点 维护:始终指向已反转链表的首节点 更新:每轮 pre = cur(cur 被接入反转链表头部) |
cur | ListNode* | 定义:当前正在处理的节点 维护:指向原链表中下一个待反转的节点 更新:每轮 cur = nxt(移到下一个) |
nxt | ListNode* | 定义:cur 的原后继(改指针前先保存,防断链) 维护:每轮保存 cur.next 更新:nxt = cur.next(在 cur.next 被改写之前) |
落码步骤
1. pre = None, cur = head
2. 循环:nxt = cur.next(保存后继,防断链)
3. cur.next = pre(反转指针)
4. pre = cur; cur = nxt(两指针前移)
5. 返回 pre
代码实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
pre = None # 已反转部分的头节点
cur = head # 当前正在处理的节点
while cur:
nxt = cur.next # 先保存后继,防断链
cur.next = pre # 反转指针
pre = cur # pre 前移
cur = nxt # cur 前移
return pre
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr; // 已反转部分的头节点
ListNode* cur = head; // 当前正在处理的节点
while (cur) {
ListNode* nxt = cur->next; // 先保存后继,防断链
cur->next = pre; // 反转指针
pre = cur; // pre 前移
cur = nxt; // cur 前移
}
return pre;
}
};
// 时间 O(n),空间 O(1)
// 递归版:reverseList(head.next) 后 head.next.next = head; head.next = null;
复杂度分析
时间复杂度
O(n)
空间复杂度
O(1)
常见坑
顺序!必须先 nxt = cur.next 保存,再修改 cur.next。反过来就会「断链」——丢失后续所有节点。
返回值是 pre 不是 cur:循环结束时 cur 是 None,pre 才是新头。
空链表 / 单节点:while 直接跳过,返回 pre(null 或 head),行为正确。
必测边界 Case
Case 1:空链表
head = null → 输出 null
Case 2:单节点
head = [1] → 输出 [1]