首页 > 极客资料 博客日记
每日算法随笔:反转链表
2024-09-10 15:30:04极客资料围观21次
文章每日算法随笔:反转链表分享给大家,欢迎收藏极客之家,专注分享技术知识
题解:反转链表
这道题目要求我们将一个单链表进行反转,返回反转后的链表。链表的反转可以通过 迭代 和 递归 两种方法来实现。下面我们将详细解释这两种方法,并通过例子演示每一步的变化过程。
方法一:迭代法
思路:
- 我们用三个指针来完成链表的反转:
prev
表示前一个节点,curr
表示当前节点,next
表示下一个节点。 - 通过不断将当前节点的
next
指针指向prev
,实现链表的逐步反转。
迭代的步骤:
- 初始化
prev = null
和curr = head
,然后开始遍历链表。 - 在每次迭代中,先用
next
保存curr.next
,避免链表断开。 - 将
curr.next
指向prev
,反转当前节点的指向。 - 将
prev
移动到curr
,然后将curr
移动到next
,继续下一次迭代。 - 当
curr
为null
时,链表反转完成,prev
就是新的头节点。
代码实现:
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; // 将 prev 前移
curr = next; // 将 curr 前移
}
return prev; // prev 成为新链表的头节点
}
}
例子演示:
输入:head = [1,2,3,4,5]
-
初始状态:
prev = null curr = 1 -> 2 -> 3 -> 4 -> 5
-
第一步:
next = 2 -> 3 -> 4 -> 5 curr.next = prev // 1 -> null prev = 1 -> null curr = 2 -> 3 -> 4 -> 5
-
第二步:
next = 3 -> 4 -> 5 curr.next = prev // 2 -> 1 -> null prev = 2 -> 1 -> null curr = 3 -> 4 -> 5
-
第三步:
next = 4 -> 5 curr.next = prev // 3 -> 2 -> 1 -> null prev = 3 -> 2 -> 1 -> null curr = 4 -> 5
-
第四步:
next = 5 curr.next = prev // 4 -> 3 -> 2 -> 1 -> null prev = 4 -> 3 -> 2 -> 1 -> null curr = 5
-
第五步:
next = null curr.next = prev // 5 -> 4 -> 3 -> 2 -> 1 -> null prev = 5 -> 4 -> 3 -> 2 -> 1 -> null curr = null
输出:[5, 4, 3, 2, 1]
复杂度分析:
- 时间复杂度:O(n),其中
n
是链表的节点数。我们只遍历了链表一次。 - 空间复杂度:O(1),只用了常数级别的额外空间。
方法二:递归法
思路:
- 我们递归地反转链表的后续部分,直到最后一个节点成为新的头节点。
- 每次递归返回时,将当前节点的下一个节点的
next
指向自己,同时将自己的next
置为空,完成反转。
递归步骤:
- 如果
head
为null
或者head.next
为null
,直接返回head
作为新的头节点(即递归的终止条件)。 - 递归反转剩余的链表。
- 将当前节点的下一个节点的
next
指向自己,同时将自己的next
置为空。 - 返回新的头节点。
代码实现:
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; // 返回新的头节点
}
}
例子演示:
输入:head = [1,2,3,4,5]
-
初始递归:
reverseList(1)
递归调用reverseList(2)
。
-
递归到最后一个节点:
reverseList(5)
返回5
作为新头节点。
-
逐步反转链表:
-
reverseList(4)
:head = 4 -> 5 反转后 5 -> 4 head.next.next = 4 head.next = null // 4 -> null 返回 5 -> 4 -> null
-
reverseList(3)
:head = 3 -> 4 -> null 反转后 5 -> 4 -> 3 head.next.next = 3 head.next = null 返回 5 -> 4 -> 3 -> null
-
reverseList(2)
:head = 2 -> 3 -> null 反转后 5 -> 4 -> 3 -> 2 head.next.next = 2 head.next = null 返回 5 -> 4 -> 3 -> 2 -> null
-
reverseList(1)
:head = 1 -> 2 -> null 反转后 5 -> 4 -> 3 -> 2 -> 1 head.next.next = 1 head.next = null 返回 5 -> 4 -> 3 -> 2 -> 1 -> null
-
输出:[5, 4, 3, 2, 1]
复杂度分析:
- 时间复杂度:O(n),其中
n
是链表的节点数。递归过程中每个节点只处理一次。 - 空间复杂度:O(n),递归调用的栈深度为
n
。
总结:
- 迭代法:通过三个指针逐步反转链表,时间和空间复杂度都为 O(n) 和 O(1),适合在空间要求较严格的场景下使用。
- 递归法:利用函数调用栈进行递归,代码简洁直观,但需要 O(n) 的额外空间。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:manim边学边做--常用多边形
下一篇:RS485与ModbusRTU
相关文章
最新发布
- Nuxt.js 应用中的 prerender:routes 事件钩子详解
- 【问题解决】Tomcat由低于8版本升级到高版本使用Tomcat自带连接池报错无法找到表空间的问题
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit
- 六、Spring Boot集成Spring Security之前后分离认证流程最佳方案
- 《JVM第7课》堆区
- .NET 8 高性能跨平台图像处理库 ImageSharp
- 还在为慢速数据传输苦恼?Linux 零拷贝技术来帮你!
- 刚毕业,去做边缘业务,还有救吗?
- 如何避免 HttpClient 丢失请求头:通过 HttpRequestMessage 解决并优化
- 让性能提升56%的Vue3.5响应式重构之“版本计数”