真实面经题目 · 原创解析
如何反转单链表?
反转单链表的标准做法是迭代维护 prev、curr、next 三个指针,逐个改变 next 指向,最后返回 prev。
出现于:华为 · 算法
真实面经题目 · 原创解析
反转单链表的标准做法是迭代维护 prev、curr、next 三个指针,逐个改变 next 指向,最后返回 prev。
反转单链表可以用三指针迭代。prev 初始为空,curr 指向头节点;每轮先保存 next = curr.next,避免断链后丢失后续节点;再令 curr.next = prev,把当前节点反向;然后 prev = curr、curr = next。循环结束时 prev 就是新头节点。时间复杂度 O(n),额外空间 O(1)。面试时要覆盖空链表、单节点链表、是否允许原地修改,以及递归解法的栈空间风险。
prev 表示已经反转好的链表头,curr 表示当前要处理的节点,next 用来临时保存原链表后续节点,防止改指针后断链。
每轮必须先保存 curr.next,再把 curr.next 指向 prev。如果先改指向,就会丢失原来后续链表的入口。
当前节点接到反转链表前端后,prev 前进到 curr,curr 前进到 next。这个过程不断把未处理节点移入已反转部分。
当 curr 为空时,原链表全部处理完,prev 指向新的头节点。空链表时 prev 也为空,单节点时会原样返回该节点。
递归也可以反转链表,但会消耗 O(n) 调用栈。面试现场优先写迭代版本,再补充递归思路和栈空间风险,避免深链表栈溢出。
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.next 指向当前节点,再把当前节点 next 置空。
需要记录区间前驱和区间后继,在区间内部反转后重新接回两端。
正确实现每轮只改当前节点 next 指向 prev,最后原头节点 next 会指向空;也可用快慢指针做防御性检查。