206. 反转链表(力扣LeetCode)

文章目录

  • 206. 反转链表
    • 题目描述
    • 双指针
    • 递归

206. 反转链表

题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
206. 反转链表(力扣LeetCode)_第1张图片

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

示例 2:
206. 反转链表(力扣LeetCode)_第2张图片

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

示例 3:

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

提示:

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

双指针

该段代码的目标是实现链表的反转。这里使用了迭代法,不断地更改当前节点的 next 指针,直到遍历完整个链表。反转过程中,需要一个额外的指针 tmp 来保存下一个节点的信息,以防止链表断裂。

  • ListNode* cur = head; 初始化当前节点指针 cur,开始时指向链表头 head。
  • ListNode* pre = nullptr; 初始化前一个节点指针 pre,开始时没有前一个节点,因此设置为 nullptr。
  • 在 while(cur) 循环中,只要当前节点不是 nullptr(即没有到达链表尾部),循环就继续。
  • ListNode* tmp = cur->next; 保存当前节点 cur 的下一个节点,因为 cur 的 next 指针即将改变。
  • cur->next = pre; 反转操作,让当前节点 cur 的 next 指针指向前一个节点 pre。
  • pre = cur; 和 cur = tmp; 更新 pre 和 cur 指针,为下一次迭代移动到下一个节点。
    循环结束时,pre 指向最后一个处理的节点,这时 pre 就是反转后链表的新头节点,因此函数最后返回 pre。
class Solution {
public:
    // 反转链表的函数
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head;  // cur指针用于遍历链表,初始指向头节点
        ListNode* pre = nullptr;  // pre指针用于追踪cur的前一个节点,初始为nullptr

        // 遍历链表直到cur指针为空,即到达链表末尾
        while(cur) {
            // tmp暂存cur的下一个节点,因为接下来要改变cur->next的指向
            ListNode* tmp = cur->next;

            // 反转cur指针的指向,将cur的next指向pre
            cur->next = pre;

            // 移动pre和cur指针,为下一次迭代做准备
            pre = cur;  // pre向前移动到cur的位置
            cur = tmp;  // cur向前移动到原来cur的下一个节点
        }

        // 当循环结束时,cur为nullptr,pre指向原链表的最后一个节点,即反转后的链表头
        return pre;
    }
};

递归

在这个代码中,reverseList 是一个公有方法,它为用户提供了反转链表的接口。它依赖于一个私有递归辅助函数 reverse 来实际执行反转操作。递归辅助函数 reverse 接受两个参数:当前要处理的节点 cur 和前一个节点 pre。通过不断地将 cur->next 指向 pre 并递归调用 reverse,链表被逐个节点反转,直到 cur 为 nullptr,意味着链表已经完全反转,此时 pre 是新链表的头节点。

// 解决方案类,包含反转链表的方法
class Solution {
public:
    // 公有方法,接口,它接受一个链表的头节点,并返回反转后的链表的头节点
    ListNode* reverseList(ListNode* head) {
        // 调用私有的递归函数来执行实际的反转操作
        // 初始调用时,先前节点设置为nullptr,因为头节点没有前驱
        return reverse(head, nullptr);
    }

private:
    // 私有递归函数,用于实际执行反转过程
    // 参数cur是当前正在访问的节点
    // 参数pre是cur节点之前的节点,即在反转后,cur应该指向的节点
    ListNode* reverse(ListNode* cur, ListNode* pre) {
        // 如果当前节点为空(nullptr),意味着我们到达了原始链表的尾端
        // 此时,pre是反转链表的头节点,应返回它
        if (cur == nullptr) return pre;

        // 保存当前节点的下一个节点,因为接下来需要改变当前节点的next指针
        ListNode* tmp = cur->next;
        // 反转操作:将当前节点的next指针指向pre节点
        cur->next = pre;
        // 递归调用reverse函数处理剩余的链表部分
        // 此时,当前节点成为下一步的pre,而tmp(原cur->next)成为下一步的cur
        return reverse(tmp, cur);
    }
};

你可能感兴趣的:(leetcode,链表,leetcode,数据结构,c++)