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,然后同步向后移动 prevcurr 指针。

关键步骤

  1. 初始化:创建两个指针,prev = null(表示反转后链表的尾部)和 curr = head(当前要处理的节点)。

  2. 循环遍历:当 curr 不为 null 时,持续循环。 a. 保存下一个节点:用一个临时变量 temp 保存 curr.next,防止链表断裂后找不到后续节点。 b. 反转指针:将当前节点 currnext 指针指向前一个节点 prev。这是反转操作的核心。 c. 移动 prev 指针prev 向前移动到 curr 的位置。 d. 移动 curr 指针curr 向前移动到之前保存的 temp 的位置,准备处理下一个节点。

  3. 返回结果:当循环结束时(currnull),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 等常数个额外变量作为指针,空间消耗是恒定的。

相关题目

总结

本题是链表操作的基石,也是面试中考察频率极高的一道题。其迭代解法清晰地展示了如何通过几个指针的巧妙配合来原地修改数据结构。深刻理解指针的移动和指向的改变过程,是掌握链表相关算法的关键第一步。

Copyright © Jun 2025 all right reserved,powered by Gitbook该文件修订时间: 2025-07-03 17:35:08

results matching ""

    No results matching ""

    results matching ""

      No results matching ""