力扣刷题#14:LeetCode0206-反转链表

题目

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

输入:head = [1, 2, 3, 4, 5]
输出:[5, 4, 3, 2, 1]

链表基础

节点结构

struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

每个节点有两部分:

  • val:存储的数据
  • next:指向下一个节点的指针,最后一个指向 nullptr

链表和数组最大的区别:数组是连续内存,链表是分散内存。所以不能 list[2] 直接跳到第三个元素,只能从 head 开始顺着 next 走。

head ──→ [1 | next] ──→ [2 | next] ──→ [3 | next] ──→ nullptr

版本一:迭代法(核心)

思路

用三个指针:

  • prev:指向已反转部分的头(初始为 nullptr
  • cur:当前要处理的节点(初始为 head
  • tmp:保存下一个节点,防止断链

每一轮只做一件事:把 cur→next 掰向 prev

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) return head;

        ListNode* prev = nullptr;
        ListNode* cur = head;
        while (cur) {
            ListNode* tmp = cur->next;  // 1. 保存下一个
            cur->next = prev;            // 2. 反转指向
            prev = cur;                  // 3. prev 前进
            cur = tmp;                   // 4. cur 前进
        }
        return prev;                     // 新头
    }
};

手走一遍 [1, 2, 3, 4]

初始:prev=null, cur=①

第1轮:tmp=②, ①→next=null, prev=①, cur=②
  null ← ①    ② → ③ → ④ → null

第2轮:tmp=③, ②→next=①, prev=②, cur=③
  null ← ① ← ②    ③ → ④ → null

第3轮:tmp=④, ③→next=②, prev=③, cur=④
  null ← ① ← ② ← ③    ④ → null

第4轮:tmp=null, ④→next=③, prev=④, cur=null
  null ← ① ← ② ← ③ ← ④

循环结束,return prev=④

踩坑记录:while 条件写错了

❌ 错误写法:

while (cur->next) {     // 最后一个节点进不了循环!
    ...
}
return cur;             // 返回了最后一个未被反转的节点

为什么错?cur 走到最后一个节点(4)时,cur→nextnullptr,循环直接退出——但最后一个节点还没有被反转指向。

✅ 正确写法:

while (cur) {           // 所有节点都会处理
    ...
}
return prev;            // 循环结束时 prev 停在最后一个节点
写法 处理了几个节点 返回值
while(cur->next) 前 n-1 个 最后一个未处理 ❌
while(cur) 全部 n 个 prev 是新头 ✅

为什么 return prev

循环结束时:

  • cur 已经移到了 nullptr(越界了)
  • prev 停在了原来的最后一个节点上——也就是反转后的新头

核心原则

每一轮只掰一个节点的指向,掰完往前走。 不要试图在一轮里同时改两个节点的指向——会搞丢后面的链。


版本二:递归法

我的 AC 代码(含注释)

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) return head;

        // 递归写法
        ListNode* newhead = reverseList(head->next);
        // 新的链表头是反转链表函数返回的头,直到尾节点才停止递归
        // 现在尾节点才是 newhead 节点

        head->next->next = head;
        // 现在的头节点是该层函数结束前的头节点
        // 现在节点的下一个节点的指针指向现在的头,也就是反转下一个节点的指向

        head->next = nullptr;
        // 现在的 head 变成新的尾节点

        return newhead;
    }
};

一句话理解

先反转后面的,再把 head 接到反转结果的尾巴上。

手走一遍 [1, 2, 3, 4]

递归入栈(从上往下):

调用 做什么
1 reverse(1) head→next=2≠null → 递归 reverse(2)
2 reverse(2) head→next=3≠null → 递归 reverse(3)
3 reverse(3) head→next=4≠null → 递归 reverse(4)
4 reverse(4) head→next=null → 出口!return 4

回归(从下往上,关键反转操作):

每一层回归时,都执行两个操作:

操作①:head→next→next = head     ← 先连线:让后面的节点反过来指向 head
操作②:head→next = nullptr        ← 再断线:head 的 next 清空,变成新尾巴

reverse(3) 收到 newHead=4:

执行前:4→null(3→next还指向4)
此时 head=3,head->next=4
操作①:head→next→next = head 
       即 4 →next = 3
操作②:head→next = nullptr 
       即 3→next = null
结果:4→3→null
return newHead=4

reverse(2) 收到 newHead=4:

执行前:4→3→null(2→next还指向3→next已断)
此时head=2,head->next=3
操作①:head→next→next = head 
       即 3→next = 2
操作②:head→next = nullptr 
       即 2 → next = null
结果:4→3→2→null
return newHead=4

reverse(1) 收到 newHead=4:

执行前:4→3→2→null(1→next还指向2)
此时head=1,head->next=2
操作①:head→next→next = head
       即 2→next = 1
操作②:head→next = nullptr
       即 1→next = null

结果:4→3→2→1→null ✅
return newHead=4

最难理解的一句:head->next->next = head

把它拆开看:

// head=1, head->next=2
head->next->next = head;
// 等价于:2->next = 1
// 意思:让 head 的下一个节点(2)反过来指向 head(1)

为什么先连线再断线? 因为 head→next 还保留着原始指向下一个节点的值,必须先用它来连上新节点,再 head→next = nullptr。如果顺序反了:

head->next = nullptr;              // 先断线
head->next->next = head;           // null->next → 崩了!

完整变化图(递归回归三步)

第3层回归后:  4 → 3 → null
第2层回归后:  4 → 3 → 2 → null
第1层回归后:  4 → 3 → 2 → 1 → null ✅

迭代 vs 递归对比

对比 迭代 递归
思路 从左到右依次反转 从右到左,先反转后面再处理头部
空间 O(1) O(n) 递归栈深度
面试要求 必须会 加分项

复杂度分析

维度 说明
时间复杂度 O(n) 每个节点处理一次
空间复杂度(迭代) O(1) 只用了三个指针
空间复杂度(递归) O(n) 递归调用的栈深度

本文档由 AI 辅助生成,作者提供问题,思路和代码,AI仅负责文本修饰,综合获得以上内容。

posted @ 2026-06-11 15:25  STA_running  阅读(10)  评论(0)    收藏  举报