0206.反转链表
难度:🟢 简单
标签:递归
、链表
链接:206. 反转链表
题目描述
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
解题思路
核心思想
本题的核心思想是在遍历原始链表的同时,逐个地改变节点的 next
指针方向,使其指向前一个节点。为了在改变指针方向后仍能找到下一个要处理的节点,我们需要一个临时变量来提前保存它。
思路选择
迭代法(双指针) 是解决此问题最直观、最高效的方法之一。我们使用两个指针来完成反转:
prev
指针:用于记录当前节点的前一个节点,初始化为null
,它最终将成为新链表的头节点。curr
指针(在您的代码中是after
):指向当前正在处理的节点,初始化为head
。
通过迭代,不断地将 curr
指针的 next
指向 prev
,然后同步向后移动 prev
和 curr
指针。
关键步骤
初始化:创建两个指针,
prev = null
(表示反转后链表的尾部)和curr = head
(当前要处理的节点)。循环遍历:当
curr
不为null
时,持续循环。 a. 保存下一个节点:用一个临时变量temp
保存curr.next
,防止链表断裂后找不到后续节点。 b. 反转指针:将当前节点curr
的next
指针指向前一个节点prev
。这是反转操作的核心。 c. 移动prev
指针:prev
向前移动到curr
的位置。 d. 移动curr
指针:curr
向前移动到之前保存的temp
的位置,准备处理下一个节点。返回结果:当循环结束时(
curr
为null
),prev
指针就指向了原始链表的最后一个节点,也就是反转后新链表的头节点。返回prev
。
代码实现
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function (head) {
let prev = null; // 前一个节点,初始化为 null
let curr = head; // 当前节点
while (curr !== null) {
// 1. 临时保存下一个节点
let temp = curr.next;
// 2. 反转指针方向
curr.next = prev;
// 3. 移动 prev 和 curr 指针
prev = curr;
curr = temp;
}
// 循环结束时,prev 指向新的头节点
return prev;
};
复杂度分析
时间复杂度:O(n) 其中 n 是链表的长度。我们只需要对链表进行一次完整的遍历。
空间复杂度:O(1) 我们只使用了
prev
,curr
,temp
等常数个额外变量作为指针,空间消耗是恒定的。
相关题目
0092.反转链表 II (反转链表的一部分)
总结
本题是链表操作的基石,也是面试中考察频率极高的一道题。其迭代解法清晰地展示了如何通过几个指针的巧妙配合来原地修改数据结构。深刻理解指针的移动和指向的改变过程,是掌握链表相关算法的关键第一步。