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 指针方向,直到整个链表翻转完成。

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

相关推荐
24k小善3 分钟前
ApacheJmeter使用权威指南
java·大数据·spring·云计算
LouisCanBe7 分钟前
Python 环境管理工具选择与安装实践:Conda 与 uv
linux·python
wuxiguala10 分钟前
【C/S通信仿真】
c语言·开发语言
2301_8170316510 分钟前
C语言-- 深入理解指针(3)
c语言·开发语言
IT瘾君11 分钟前
Java基础:网络编程UDP&TCP详解
java·网络·udp·tcp
limengshi13839216 分钟前
使用Python将YOLO的XML标注文件转换为TXT文件格式
xml·python·yolo
海绵宝宝的月光宝盒21 分钟前
[STM32] 4-1 UART与串口通信
c语言·开发语言·笔记·stm32·单片机
矢志航天的阿洪21 分钟前
伪谱法求解最优控制问题(附Python代码)
开发语言·python
码熔burning34 分钟前
【MQ篇】初识MQ!
java·微服务·mq
贵沫末37 分钟前
AI——神经网络以及TensorFlow使用
人工智能·python·线性回归