数据结构算法之链表篇-反转链表的原理及代码实现

力扣题目链接https://leetcode.cn/problems/spiral-matrix-ii/

1.1 问题描述:反转链表

题意:反转一个单链表。

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

1.2 思路:

刚学链表反转,别一上来就新建链表存元素 —— 完全没必要!不用加删节点,只改每个节点的next指针方向,就能高效反转,还省内存。

比如原链表是 1→2→3→4→5(头是 1),反转后要成 5→4→3→2→1(头是 5)。全程只改 “指向”:原来 1 指 2,现在 2 指 1;原来 2 指 3,现在 3 指 2,以此类推。

为了让每个读者都能一眼看明白 “只改指针、不增删节点” 的反转逻辑,下面用 方框代表节点箭头代表 next 指针,分 “原链表”“反转关键步骤”“反转后链表” 三部分展示:

1.21 原链表(未反转前)

【原头节点:1】
 1  →  2  →  3  →  4  →  5  →  null
 □     □     □     □     □
val:1 val:2 val:3 val:4 val:5
next:2 next:3 next:4 next:5 next:null

说明:每个节点的 next 都 “往后指”,最终指向 null,整个链表的起点是节点 1。

1.22 反转关键步骤(只改箭头方向,节点不变)

反转的核心是 “逐个把节点的 next 从‘往后指’改成‘往前指’”,这里挑 3 个关键节点的变化展示:

a. 第一步:改节点 2 的 next 指向

原来节点 2 的 next 指向 3,现在改成指向 1:

 1  ←  2  →  3  →  4  →  5  →  null
 □     □     □     □     □
val:1 val:2 val:3 val:4 val:5
next:2 next:1 next:4 next:5 next:null  (节点2的next从3→1)
b. 第二步:改节点 3 的 next 指向

原来节点 3 的 next 指向 4,现在改成指向 2:

 1  ←  2  ←  3  →  4  →  5  →  null
 □     □     □     □     □
val:1 val:2 val:3 val:4 val:5
next:2 next:1 next:2 next:5 next:null  (节点3的next从4→2)
c. 最后一步:改节点 5 的 next 指向

原来节点 5 的 next 指向null,现在改成指向 4:

 1  ←  2  ←  3  ←  4  ←  5  →  null
 □     □     □     □     □
val:1 val:2 val:3 val:4 val:5
next:2 next:1 next:2 next:3 next:4  (节点5的next从null→4)

1.23 反转后链表(最终结果)以及动态展示

【新头节点:5】
 null  ←  1  ←  2  ←  3  ←  4  ←  5
          □     □     □     □     □
val:1 val:2 val:3 val:4 val:5
next:null next:1 next:2 next:3 next:4

动态展示指针变化

2.1 代码实现 

/**
 * 反转单链表的迭代实现
 * 核心思路:通过调整每个节点的next指针方向,将原链表从"顺向链接"改为"逆向链接"
 * 
 * @param head 原链表的头节点
 * @return 反转后新链表的头节点(即原链表的尾节点)
 */
public ListNode reverseList(ListNode head) {
    // 边界条件:空链表或仅含一个节点时,无需反转,直接返回原头节点
    if (head == null || head.next == null) {
        return head;
    }

    // 初始化指针:
    ListNode pre = null;       // 指向当前节点的"前一个节点"(初始为null,因原头节点反转后需指向null)
    ListNode curr = head;      // 指向当前正在处理的节点(初始为原头节点)
    ListNode nextTemp = null;  // 暂存当前节点的"下一个节点"(防止修改curr.next后丢失后续节点)

    // 遍历链表,逐节点反转指针方向
    while (curr != null) {
        nextTemp = curr.next;  // 1. 先保存当前节点的下一个节点,避免链表断裂
        curr.next = pre;       // 2. 反转当前节点的指针:从指向后一个节点改为指向前一个节点
        pre = curr;            // 3. 移动pre指针:将pre更新为当前节点(为下一次反转做准备)
        curr = nextTemp;       // 4. 移动curr指针:处理下一个节点(使用之前保存的nextTemp)
    }

    // 循环结束时,curr为null,pre指向原链表的最后一个节点(即反转后新链表的头节点)
    return pre;
}

个人总结学习用,对部分内容进行了简单的处理和归纳,如有谬误,希望大家指出,
持续修订更新中。

参考文档:

① 程序员 Carl. 代码随想录(LeetCode 算法刷题攻略官网)[EB/OL]. (2025-02)[2025-10]. https://www.programmercarl.com/. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值