本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接
一、题目描述
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。
二、思路分析
- 链表操作正常就是循环遍历链表从而进行操作。在leetcode官网中也给了我们提示实现反转可以通过迭代和递归两种方式。
- 下面我们通过两种方式来分析下实现逻辑
迭代
- 首先我们需要借助于独立的三个节点来完成迭代反转的操作。分别是
preNode
,nextNode
,currentNode
。 分别用于表示现阶段的前置节点、后置节点、当前节点。 - 下面我们通过动画来解释下相邻的两个节点是如何依赖这三个节点实现反转的
- 两两节点都是这么操作的。当操作到最后的时候preNode就是我们原链表中的最后的节点,反转之后恰恰是我们反转链表的开始节点所以直接将preNode返回即可
public ListNode reverseList(ListNode head) {
ListNode preNode = null;
ListNode nextNode = null;
ListNode currentNode = head;
while (currentNode != null) {
nextNode = currentNode.next;
currentNode.next = preNode;
preNode = currentNode;
currentNode = nextNode;
}
return preNode;
}
- 原理+代码更香哦。下面我们直接上leetcode跑测试用例
- 结果很是完美,执行速度上已经到达天花板了,在内存消耗上也不是很低90%笔者认为已经很优秀了。
递归
- 其实递归在理解上应该更好的理解。递归是先进入最底层开始执行。递归和迭代在执行的方向上是相反的。
- 递归最终先执行右侧相邻节点。只需要将两个指针指向修改就可以了。递归是最方便的。但是执行上没有迭代性能高
public ListNode reverseList(ListNode head) {
if (head == null) {
return head;
}
return digui(head, head.next);
}
public ListNode digui(ListNode preNode , ListNode head) {
if (head == null) {
return preNode;
}
ListNode diguiNode = digui(head, head.next);
head.next = preNode;
preNode.next=null;
return diguiNode;
}
四、总结
- 往往最简单的思维性能并不是最优的。
- 在链表的操作中,借助辅助节点是必要的。往往我们需要辅助节点来临时存储交换节点用来
点赞吧!