4.反转链表

leetcode.cn/problems/re...

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

ini 复制代码
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]

示例 2:

ini 复制代码
输入: head = [1,2]
输出: [2,1]

示例 3:

ini 复制代码
输入: head = []
输出: []

提示:

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

进阶: 链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

java 复制代码
class Solution {

    public static void main(String[] args) {
        ListNode node = new ListNode(0);
        node.next = new ListNode(1);
        node.next.next = new ListNode(2);
        node.next.next.next = new ListNode(3);
        node.next.next.next.next = new ListNode(4);
        reverse(node);
    }

    public ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null || fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    public static ListNode reverse(ListNode head) {
        ListNode cur = head;
        ListNode pre = null;
        while (cur != null) {
            //暂存后继节点 cur.next=1
            ListNode tmp = cur.next;
            //将原来的头结点给cur的下一个节点
            cur.next = pre;
            //将当前cur作为pre也就是头结点,也就是遍历到谁谁就是头结点,原来的头结点要给到当前正在遍历的节点的下一个节点
            pre = cur;
            //假设pre=0 cur=1 cur.next=2
            //那么经过上面的操作以后,cur.next=0, pre = cur = 1 即 pre=1,pre.next=0 相当于是做了换位操作
            cur = tmp;
        }
        return pre;
    }
}

方法一:迭代

假设链表为 1→2→3→∅ 我们想要把它改成 ∅←1←2←3。

在遍历链表时,将当前节点的 next\textit{next}next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。

java 复制代码
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

时间复杂度:O(n)

其中 nnn 是链表的长度。需要遍历链表一次。

空间复杂度:O(1)。

方法二:递归

递归版本稍微复杂一些,其关键在于反向工作。假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?

java 复制代码
class Solution {
    public 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;
    }
}

复杂度分析

时间复杂度:O(n),其中 n 是链表的长度。需要对链表的每个节点进行反转操作。

空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 n 层。

相关推荐
LabVIEW开发5 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
量化分析码农6 小时前
【Python量化波动率实战 01】波动率是怎么算的:年化、滚动与区间估计一次讲清
后端
特立独行的猫A6 小时前
AI 时代,我为什么推荐用 cj-tauri 开发桌面应用
java·后端·python
金銀銅鐵6 小时前
从一个类名到一张类图:用反射自动生成 PlantUML
java·后端·uml
严肃小白兔7 小时前
MATLAB 数值计算中的精度与误差问题:浮点运算、误差传播与数值稳定性
人工智能·算法·matlab
追逐时光者7 小时前
一款基于 .NET 开源、免费的数据库自治诊断平台
后端·.net
追逐时光者7 小时前
让 GitHub Copilot 更懂你的 .NET 代码风格:一份精简实用的 Copilot Instructions
后端·.net
青少儿编程课堂8 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
小满zs8 小时前
Go语言第十八章(架构设计)
后端·go
山甫aa8 小时前
锁一篇搞定:乐观锁、悲观锁、CAS、数据库锁与分布式锁【从零开始的 Web 后端学习】
java·数据库·分布式·后端·学习·web