题目重点:Nvidia Deep Learning 技术电面明确出现 reverse linked list;本文给原地三指针解法、正确性不变量、边界和独立验证。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 输入是有限、无环的单向链表,节点含 value 和 next;返回反转后的头节点。题目未明确节点定义。
- 训练版必须复用原节点,不新建数据节点;空链表返回 None,单节点返回自己。
- 若原链表可能有环、共享尾链或外部代码持有中间节点,必须先问所有权与突变语义,不能直接套标准原地算法。
解题路线
- 维护 previous 指向已处理前缀的反转头,current 指向未处理后缀的头。每轮先保存 following=current.next,避免改指针后失去后缀入口。
- 把 current.next 指向 previous,再将 previous=current、current=following。循环不变量:previous 可达的节点顺序正好是原已处理前缀的反序;current 可达的未处理后缀保持原序,两段不丢节点。
- current 变为 None 时,所有节点都在 previous 链中且顺序反转,返回 previous。每轮处理一个节点,所以循环终止。
手动走一遍
1→2→3:第一轮保存 2,令 1.next=None;第二轮保存 3,令 2.next=1;第三轮令 3.next=2。最后 previous 指向 3,输出 3→2→1。若一开始 head=None,循环不执行。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Reverse an acyclic singly linked list in place."""
from dataclasses import dataclass
@dataclass
class Node:
value: int
next: "Node | None" = None
def reverse_list(head: Node | None) -> Node | None:
previous = None
current = head
while current is not None:
following = current.next
current.next = previous
previous = current
current = following
return previous
复杂度
N 个节点各访问一次,时间 O(N);除三个指针变量外不分配随 N 增长的内存,辅助空间 O(1)。若用递归,调用栈会是 O(N),很长链表可能栈溢出。
易错点与追问
容易失分的边界
- 先写 current.next=previous,再读取原 current.next,会丢失剩余链表。
- 只调整节点值或新建节点,却声称完成原地节点反转;训练版要求节点身份不变。
- 忘记把旧头的 next 置为 None,可能形成环。
- 对空输入直接访问 head.next,产生异常。
继续深挖
- 若要求反转 [left,right] 子链,需要保存区间前驱与后继并在局部反转后接回。
- 若每 K 个节点反转,先确认不足 K 个的尾段是否保留原序,逐块维持连接不变量。
- 若输入可能有环,先检测并约定拒绝或先断环;仅靠标准循环会无限运行。
