Java 实现单链表翻转(附详细注释)

1. 引言

单链表(Singly Linked List)是一种常见的数据结构,在算法和数据结构的学习中占有重要地位。翻转单链表是一道经典的面试题,本文将介绍几种常见的 Java 实现方法,并详细讲解关键步骤的含义。

2. 单链表定义

我们可以先定义一个链表节点类:

java 复制代码
class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

3. 迭代法实现链表翻转(附详细注释)

迭代法是最常用的方法之一,使用三个指针完成整个翻转过程:

java 复制代码
public class ReverseLinkedList {
    public static ListNode reverseList(ListNode head) {
        ListNode prev = null;       // 初始时,前一个节点指针为 null
        ListNode current = head;    // 当前处理的节点从链表头开始

        while (current != null) {
            ListNode nextNode = current.next; // 1. 暂存当前节点的下一个节点

            current.next = prev;              // 2. 将当前节点的指针指向前一个节点
            /*
             * 原本 current 节点是指向下一个节点的,
             * 比如 current 是 2,它的 next 是 3,
             * 这一步将它反过来指向前面的 prev,
             * 也就是把 2 -> 3 改成 2 -> 1(假设 prev 是 1),
             * 从而实现链条的反向连接。
             */

            prev = current;                   // 3. 移动 prev 指针
            /*
             * 这一步是让 prev 继续前进,指向当前处理好的节点,
             * 为下一轮翻转做准备。
             * 假设刚刚处理的是 2,现在 prev 变成 2,
             * 这样下一轮就可以把 3 的指针指向 2 了。
             */

            current = nextNode;               // 4. 继续处理下一个节点
        }

        return prev; // 最终 prev 会指向新的头节点
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        ListNode reversedHead = reverseList(head);

        while (reversedHead != null) {
            System.out.print(reversedHead.val + " -> ");
            reversedHead = reversedHead.next;
        }
        System.out.println("NULL");
    }
}

复杂度分析

  • 时间复杂度:O(n),需要遍历每个节点一次;
  • 空间复杂度:O(1),只用了常数个变量。

4. 递归法实现链表翻转

递归法思路清晰,适合理解递归调用,但需要额外的调用栈空间:

java 复制代码
public class ReverseLinkedListRecursive {
    public static ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head; // 递归出口,返回最后一个节点作为新头
        }

        ListNode newHead = reverseList(head.next); // 递归反转后续节点

        head.next.next = head; // 让后一个节点指向当前节点,实现反转
        head.next = null;      // 切断当前节点与后续的连接,避免成环

        return newHead; // 返回新头节点
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        ListNode reversedHead = reverseList(head);

        while (reversedHead != null) {
            System.out.print(reversedHead.val + " -> ");
            reversedHead = reversedHead.next;
        }
        System.out.println("NULL");
    }
}

复杂度分析

  • 时间复杂度:O(n),每个节点访问一次;
  • 空间复杂度:O(n),递归调用栈占用了额外空间。

5. 总结

  • 迭代法:空间效率高,适用于大多数场景;
  • 递归法:代码简洁,适合展示递归思维,但不适合超长链表。

建议优先使用迭代法,避免递归造成的栈溢出问题。理解链表翻转的本质,就是反转每个节点的 next 指针方向,直到整个链表翻转完成。

希望本文对你理解和实现单链表翻转有所帮助!

相关推荐
汉字萌萌哒21 分钟前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
叠层归一研究院26 分钟前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
喜欢的名字被抢了33 分钟前
程序出问题怎么查,以及如何让它不掉线
java·运维·数据库
小雨笙笙39 分钟前
C语言:变量三属性——存储类型
c语言·开发语言
数据知道1 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
果果燕2 小时前
C++ 学习笔记(二):类与对象—— 构造函数与析构函数
开发语言·c++
江畔柳前堤2 小时前
Function Calling 与 Tool Calling:从认知到工程的全景深度解析
开发语言·网络·人工智能·深度学习·算法·机器学习·php
2601_949950632 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐
努力的小Qin2 小时前
梯度下降如何实现参数优化:从线性回归到 Sigmoid 分类
人工智能·python·神经网络
strength_zhou20132 小时前
Python检查MongoDB索引列中的字段是否存在
python·mongodb