本文最后更新于133 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
🔗 反转链表
📌 题目描述
给你单链表的头节点 head,请你反转链表,并返回反转后的链表。
- 反转:将链表从
A → B → C → D变为D → C → B → A。 - 若链表为空或只有一个节点,返回其本身。
✅ 示例解析
示例 1:

- 输入:
head = [1,2,3,4,5] - 输出:
[5,4,3,2,1] - 解释:原链表
1→2→3→4→5,反转后变为5→4→3→2→1。
示例 2:

- 输入:
head = [1,2] - 输出:
[2,1] - 解释:
1→2变为2→1。
示例 3:
- 输入:
head = [] - 输出:
[] - 解释:空链表反转后仍为空。
⚠️ 提示
- 链表中节点的数目范围是
[0, 5000] -5000 <= Node.val <= 5000
💡 解法:迭代法(三指针)—— O(n) 时间,O(1) 空间
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode res = null; // 指向已反转部分的头节点
while (head != null) {
ListNode next = head.next; // 保存下一个节点
head.next = res; // 当前节点指向前一段反转链表
res = head; // 更新反转链表的头
head = next; // 移动到原链表的下一个节点
}
return res;
}
}
📊 复杂度分析
- 时间复杂度:O(n)
- 每个节点被访问且仅被访问一次,总共
n个节点。
- 每个节点被访问且仅被访问一次,总共
- 空间复杂度:O(1) ✅
- 仅使用常数个额外指针:
res、next、head。 - 无递归调用栈,空间效率极高。
- 仅使用常数个额外指针:
🧩 解题思路
- 核心思想:边遍历边反转,维护“已反转”部分的头节点
- 使用三个关键变量:
head:指向原链表当前待处理的节点。res:指向已反转部分的头节点(初始为null)。next:临时保存head.next,防止断链后丢失后续节点。
- 使用三个关键变量:
- 反转步骤(每轮操作):java深色版本
ListNode next = head.next; // 1. 保存下一个节点 head.next = res; // 2. 当前节点指向前一段反转链表 res = head; // 3. 更新反转链表的头为当前节点 head = next; // 4. 移动到原链表的下一个节点这四步实现了指针的“翻转”和“推进”。 - 举例说明:
对head = [1,2,3,4,5]:步骤headresnext操作初始1→2→3→4→5null–11→…null2→3→4→51.next = null,res = 1,head = 222→…1→null3→4→52.next = 1,res = 2,head = 333→…2→1→null4→53.next = 2,res = 3,head = 444→…3→2→1→null54.next = 3,res = 4,head = 555→…4→3→2→1→nullnull5.next = 4,res = 5,head = null结束null5→4→3→2→1→null-返回res✅ - 边界处理:
- 空链表:
head == null,直接返回null。 - 单节点:
head.next == null,直接返回head。 - 多节点:循环处理直到
head == null。
- 空链表:
- 为什么
res最终是新头?res始终指向已反转链表的头节点。- 每次将
head插入到res前面,res就更新为新的头。 - 最终
res指向原链表的最后一个节点,即新链表的头。

