




迭代法用prev、curr、next三指针,先保存next再反转,返回prev;递归法以子链表新头为返回值,需断原链并重连,注意空指针与成环。
迭代反转的关键在于维护三个指针:prev、curr、next,避免在修改 curr->next 时丢失后续节点。常见错误是先改 curr->next 再取 next,导致链表断裂。
适用场景:空间受限、链表很长、需稳定 O(1) 额外空间。
prev 初始为 nullptr,表示新链表的尾(即原链表反转后的头的前驱)curr->next 到 next,再执行 curr->next = prev
prev,不是 curr(此时 curr 已为 nullptr)
ListNode* reverseList(ListNode* head) {
ListNode* p
rev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* next = curr->next; // 先存后继
curr->next = prev; // 反转当前边
prev = curr; // prev 前移
curr = next; // curr 前移
}
return prev; // 新头节点
}
递归写法简洁,但容易误解返回值含义——reverseList(head->next) 返回的是以 head->next 为起点的子链表反转后的**新头节点**,不是原尾节点。常见错误是试图用递归函数直接操作 head 的 next 而忽略断链与重连顺序。
适用场景:代码可读性优先、链表深度可控(避免栈溢出)。
head == nullptr || head->next == nullptr,后者保证至少有一个节点可返head->next 已指向新链表尾部,需让 head->next->next = head 完成翻转head->next = nullptr,否则形成环(尤其原链表长度 ≥ 2 时)
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
}
两类错误高频出现:一类是未判空就访问 head->next 或 curr->next,触发段错误;另一类是忘记置 head->next = nullptr 或误写成 curr->next = prev 顺序颠倒,导致反转后链表成环,遍历时无限循环。
curr != nullptr 判断,curr->next 在 curr 为 nullptr 时崩溃if (!head) return head;,漏掉 !head->next,则单节点输入会进入递归并尝试解引用空指针size 个节点且无重复地址迭代时间 O(n)、空间 O(1),递归时间 O(n)、空间 O(n)(系统栈深度)。当链表长度超过几千时,递归可能栈溢出(取决于编译器和栈大小),而迭代完全无此风险。
真正要注意的不是“怎么写”,而是“什么时候不该用递归”——尤其当输入规模不可控时,空指针检查和栈深度都得算进设计里。