sogw-三叶草️头像
关注

LeetCode206. 反转链表

题目:反转一个单链表。

struct ListNode* reverseList(struct ListNode* head){
    if(head == NULL || head->next == NULL)
        return head;

    struct ListNode* n1 = NULL, *n2 = head, *n3 = head->next;
    while(n2)
    {
        // 反转
        n2->next = n1;

        // 迭代
        n1 = n2;
        n2 = n3;
        if(n3)
            n3 = n3->next;
    }
    return n1;
}

“反转单链表”功能,将形如 1->2->3->4->5->NULL 的链表就地修改为 5->4->3->2->1->NULL。它采用的是三指针法,核心思想是在遍历链表的过程中,逐个打断原本的节点指向并让其“掉头”。

1. 边界条件拦截

if(head == NULL || head->next == NULL)
    return head;

如果传入的链表是空的,或者里面只有一个节点,那么反转后的结果就是它本身,直接返回 head  即可,无需执行后续逻辑。

2. 初始化三个核心指针

代码开头定义了三个相互配合的指针:

  • n1 (前驱指针):初始化为 NULL。原链表的第一个节点(头节点)在反转后会变成最后一个节点(尾节点),它的 next 必须指向 NULL,这就是 n1 初始为 NULL 的原因。
  • n2 (当前指针):初始化为 head。它代表当前正在被处理(准备掉头)的节点。
  • n3 (后继指针):初始化为 head->next。这正是你上一个问题中遇到的逻辑:因为在反转时会修改 n2->next 的值,如果不提前用 n3 记住下一个节点的位置,修改指针后就会和后面的链表彻底失联。

3. 循环反转与迭代

进入 while(n2) 循环,只要当前节点还有效,就持续执行以下动作:

  • 执行反转 (n2->next = n1;):这是最关键的一步,直接把当前节点 n2 的指针方向反转,让它指向上一个节点 n1。
  • 指针整体平移:完成当前节点的反转后,三个指针像履带一样集体向后滑动一步,准备处理下一个节点。
  • n1 = n2;:n1 走到当前节点的位置。
  • n2 = n3;:n2 走到下一个节点的位置。
  • if(n3) n3 = n3->next;:n3 继续往前探路。这里的 if 判断是为了安全防御——当 n2 已经走到最后一个节点时,n3 已经是 NULL 了,如果强行读取 NULL->next 会引发段错误(内存访问违规)。

4. 循环结束与返回

当 n2 变成 NULL 时,说明所有节点都已经处理完毕,跳出 while 循环。
此时,n2 掉出了链表边界,而 n1 恰好停留在原链表的最后一个节点上。这个节点也就是反转后的“新头节点”,因此最终返回 n1 即可将新的链表交接出去。

struct ListNode* reverseList(struct ListNode* head){
    if(head == NULL || head->next == NULL)
        return head;

    struct ListNode* n1 = NULL, *n2 = head, *n3 = head->next;
    while(n2)
    {
        // 反转
        n2->next = n1;

        // 迭代
        n1 = n2;
        n2 = n3;
        if(n3)
            n3 = n3->next;
    }
    return n1;
}

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2501_93884468/article/details/166794233

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--