60 秒回答模板

反转单链表可以用三指针迭代。prev 初始为空,curr 指向头节点;每轮先保存 next = curr.next,避免断链后丢失后续节点;再令 curr.next = prev,把当前节点反向;然后 prev = curr、curr = next。循环结束时 prev 就是新头节点。时间复杂度 O(n),额外空间 O(1)。面试时要覆盖空链表、单节点链表、是否允许原地修改,以及递归解法的栈空间风险。

考点 保存 next
难度 真实面经题
回答目标 讲清原理、实现和边界

深入解析

01

三指针含义

prev 表示已经反转好的链表头,curr 表示当前要处理的节点,next 用来临时保存原链表后续节点,防止改指针后断链。

02

保存后继再改指针

每轮必须先保存 curr.next,再把 curr.next 指向 prev。如果先改指向,就会丢失原来后续链表的入口。

03

推进窗口

当前节点接到反转链表前端后,prev 前进到 curr,curr 前进到 next。这个过程不断把未处理节点移入已反转部分。

04

结束返回

当 curr 为空时,原链表全部处理完,prev 指向新的头节点。空链表时 prev 也为空,单节点时会原样返回该节点。

05

递归变体

递归也可以反转链表,但会消耗 O(n) 调用栈。面试现场优先写迭代版本,再补充递归思路和栈空间风险,避免深链表栈溢出。

javascript

三指针原地反转单链表

function reverseList(head) {
  let prev = null;
  let curr = head;

  while (curr) {
    const next = curr.next;
    curr.next = prev;
    prev = curr;
    curr = next;
  }

  return prev;
}
  • 关键顺序是先保存 `next`,再改 `curr.next`,最后推进 `prev/curr`。
  • 空链表和单节点链表会自然返回,不需要额外分支。

易错点

  • 不要先改 curr.next 再保存 next,那会丢失剩余链表。
  • 不要忘记最后返回 prev,而不是原 head。
  • 不要递归后忘记把旧头节点 next 置空,否则可能形成环。

面试官追问

如何递归反转链表?

递归到尾节点作为新头,回溯时让 next.next 指向当前节点,再把当前节点 next 置空。

如何反转链表的一段区间?

需要记录区间前驱和区间后继,在区间内部反转后重新接回两端。

如何检测反转后是否成环?

正确实现每轮只改当前节点 next 指向 prev,最后原头节点 next 会指向空;也可用快慢指针做防御性检查。