【LeetCode 简单题】206. 反转链表:两种思路 + 代码详解
今天来拆解 LeetCode 上的经典简单题 ------206. 反转链表,这是链表操作的入门必刷题,同时也是很多面试的 "开胃菜"。本文会分享两种常用解法,从思路到代码逐一分析,帮你彻底搞懂链表反转的逻辑~
题目描述
给你单链表的头节点 head,请你反转链表,并返回反转后的链表。
示例 :输入:head = [1,2,3,4,5]输出:[5,4,3,2,1]
解法一:双指针法(原地反转,空间复杂度 O (1))
这是链表反转的最优解法,不需要额外空间,直接在原链表上修改指针指向。
思路分析
核心是用两个指针跟踪节点,通过 "断链 - 反转指向 - 移动指针" 的步骤,逐步将原链表的节点反向串联。
步骤拆解:
- 定义两个指针:
newHead(指向反转后的新链表头,初始为nullptr)、temp(临时存储原链表的下一个节点); - 遍历原链表,每次取出当前节点
head:- 先用
temp保存head的下一个节点(防止断链后找不到后续节点); - 把
head的next指向newHead(完成当前节点的反转); - 移动
newHead到head(新链表头更新为当前节点); - 移动
head到temp(继续遍历原链表);
- 先用
- 遍历结束后,
newHead就是反转后的链表头。
代码实现
cpp
运行
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* newHead = nullptr; // 反转后的新链表头
ListNode* temp = nullptr; // 临时存储原链表的下一个节点
while (head) {
temp = head->next; // 保存下一个节点
head->next = newHead; // 当前节点指向新链表头(反转)
newHead = head; // 新链表头更新为当前节点
head = temp; // 继续遍历原链表
}
return newHead;
}
};
解法二:辅助容器法(思路直观,空间复杂度 O (n))
如果对指针操作不熟悉,可以先用辅助容器暂存节点信息,再重新构建链表。这种方法思路更直观,适合新手理解。
思路分析
用 vector 存储原链表的所有节点值,反转容器后,基于容器中的值创建新链表。
步骤拆解:
- 遍历原链表,将每个节点的
val存入vector; - 反转
vector(此时容器内的值是原链表的逆序); - 创建一个虚拟头节点
dummy(简化新链表的串联逻辑),遍历反转后的vector,依次创建新节点并串联; - 返回虚拟头节点的
next(即新链表的头)。
代码实现
class Solution {
public:
ListNode* reverseList(ListNode* head) {
vector<int> vals;
// 1. 存储原链表的所有节点值
while (head) {
vals.emplace_back(head->val);
head = head->next;
}
// 2. 反转容器(值的顺序逆序)
reverse(vals.begin(), vals.end());
// 3. 基于反转后的值构建新链表
ListNode* dummy = new ListNode(0); // 虚拟头节点
ListNode* cur = dummy;
for (int val : vals) {
cur->next = new ListNode(val); // 创建新节点
cur = cur->next; // 移动指针
}
return dummy->next; // 虚拟头的next是新链表头
}
};
两种解法对比
| 解法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| 双指针法 | O(n) | O(1) | 追求空间效率,面试推荐写法 |
| 辅助容器法 | O(n) | O(n) | 新手理解链表反转逻辑,或需保留原链表 |
总结
反转链表是链表操作的基础题,双指针法是必须掌握的最优解(空间 O (1)、逻辑清晰),辅助容器法则是 "退而求其次" 的直观思路。建议先理解辅助容器法的逻辑,再过渡到双指针法的指针操作~
如果你有其他解法,欢迎在评论区交流~