反转链表:用双指针轻松搞定(LeetCode 206)

59 阅读2分钟

🌟 题目描述

给你单链表的头节点 head,请你反转链表,并返回反转后的链表。

示例:

输入: 12345null  
输出: 54321null

🔍 为什么用双指针?

反转链表的本质是改变每个节点的 next 指针方向
如果直接修改指针,很容易“断链”——丢失后续节点。
双指针法通过两个变量(prevcurr)协同工作,安全、高效地完成反转,且空间复杂度仅为 O(1) ,是面试官最爱的解法!


💡 双指针解法详解(JavaScript)

✅ 核心思路

  1. 初始化 prev = null(新链表的尾部),curr = head(当前处理节点)。

  2. 遍历链表,每一步:

    • 先保存 curr.next(防止断链);
    • 反转指针curr.next = prev
    • 移动指针prev = currcurr = nextTemp
  3. 循环结束后,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;
    let curr = head;

    while (curr !== null) {
        // 1. 临时保存下一个节点,防止断链
        const nextTemp = curr.next;
        // 2. 反转当前节点的指针
        curr.next = prev;
        // 3. 移动双指针
        prev = curr;
        curr = nextTemp;
    }

    // prev 即为反转后的新头节点
    return prev;
};

✅ 执行过程图解(以 [1→2→3] 为例)

初始: prev = null, curr = 123 → null

第1步:
  nextTemp = 2
  1 → null
  prev = 1, curr = 2

第2步:
  nextTemp = 3
  2 → 1 → null
  prev = 2, curr = 3

第3步:
  nextTemp = null
  3 → 2 → 1 → null
  prev = 3, curr = null

结束,返回 prev(即 3)

📊 复杂度分析

项目复杂度
时间复杂度O(n) —— 遍历一次链表
空间复杂度O(1) —— 仅用两个指针变量

优势:无递归栈开销,不依赖额外内存,适合长链表和生产环境。


🛠️ 面试小贴士

  • 必问问题:“如果链表为空或只有一个节点,代码是否仍正确?”
    ✅ 答:是的!while 循环不会执行,直接返回 null 或原节点。
  • 延伸问题:“如何反转链表的某一段?”
    → 可参考 LeetCode 92(反转链表 II),核心思想类似。

✅ 总结

反转链表是链表操作的基石,而双指针迭代法是最稳健、最高效的解法。
掌握它,不仅能秒杀 LeetCode 206,还能为后续更复杂的链表问题(如回文链表、合并链表等)打下坚实基础。

📌 记住口诀

先存后指,再移双针;循环结束,prev 即头。