LeetCode Hot 100——206.反转链表

206. 反转链表

题目描述

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

示例 1

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

示例 2

输入:head = [1,2]
输出:[2,1]

示例 3

输入:head = []
输出:[]

提示

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

一、迭代法

这种方法的思想和数组中的交换元素有点类似,只不过对于单链表来说,是交换 next 指针。这种方法需要暂存指针防止被覆盖。反转后的尾节点是 NULL,将 prev 初始化为 NULL 并作为前驱节点(即临时保存的上一个节点),解决了单链表无法得到上一个节点地址的问题。

值得注意的是,这里的 head 指的是第一个节点。所以返回的时候,prev 也是第一个节点。

代码实现

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode *prev = NULL;  // 前驱节点,初始为NULL(反转后变成尾)
    struct ListNode *curr = head;  // 当前节点
    struct ListNode *next = NULL;  // 临时保存下一个节点

    while (curr != NULL) {
        next = curr->next;   // ① 先存下后面的路
        curr->next = prev;   // ② 掉头指向前一个
        prev = curr;         // ③ 前移
        curr = next;         // ④ 前移
    }
    return prev; // 循环结束,prev就是新链表的头
}

二、递归法

这个方法实际上会占比较多的空间,并且也有点不太好理解。

代码实现

struct ListNode* reverseList(struct ListNode* head) {
    // 递归终止条件:空链表 或 只有一个节点,直接返回自身
    if (head == NULL || head->next == NULL) {
        return head;
    }

    // 递归反转 head 之后的子链表
    struct ListNode *newHead = reverseList(head->next);

    // 最难理解的一步:
    // 此时 head->next 指向的是原链表中 head 的下一个节点(即反转后子链表的尾节点)
    // 让这个尾节点的 next 指向 head,完成 head 的挂接
    head->next->next = head;
    
    // 将 head 的 next 置空,因为此时 head 应该变成新链表的尾节点
    head->next = NULL;

    return newHead; // 每一层递归都返回最顶层的 newHead(即原尾节点)
}

递归栈模拟

1 -> 2 -> 3 -> 4 为例:

reverseList(1) 调用 reverseList(2),一直压栈到 reverseList(4)

reverseList(4) 触发终止条件,返回节点 4(此时 newHead = 4)。

回到 reverseList(3)head = 3head->next = 4,执行 4->next = 33->next = NULL。返回 4

回到 reverseList(2)head = 2head->next = 3,执行 3->next = 22->next = NULL。返回 4

回到 reverseList(1)head = 1head->next = 2,执行 2->next = 11->next = NULL。返回 4
最终链表变为 4 -> 3 -> 2 -> 1 -> NULL

posted @ 2026-07-17 13:34  Javenwww  阅读(15)  评论(0)    收藏  举报