「这是我参与11月更文挑战的第 3 天,活动详情查看:2021最后一次更文挑战」
题目来源:LeetCode-206. 反转链表
题目
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
题解
提出问题
- 在反转过程中,如何保留链表节点的下一个节点不丢失?
分析 迭代
- 首先定义三个指针分为
pre
、cur
、next
,并对指针进行初始化 pre
指向null
,cur
指向头节点,next
指向cur
所指向节点的下一个节点
- 将
cur
指针所指向的节点指向pre
所指向的节点
- 移动
pre
到cur
所在的位置
- 移动
cur
到next
所在的位置
- 此时第一个节点已经反转完毕,将
next
指针指向cur
所指向节点的下一个节点。
- 重复执行上述操作,当
cur
指针指向null
的时候说明,整个链表的反转执行完毕。
总结 迭代
- 初始化哨兵节点
pre
为null
,cur
为当前节点head
- 开始循环,记录
next
为当前节点的下一个节点 - 判断当前节点是否为
null
- 分别交换
pre
、cur
、next
使其反转 - 当cur为null时跳出循环
代码实现 迭代
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(!head) return null
var pre=null
var cur = head
while(cur){
const next = cur.next;
cur.next = pre;
pre = cur
cur=next
}
return pre
};
复制代码
代码优化 迭代
通过使用ES6解构赋值进行代码优化
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(!head) return null
var pre=null
var cur = head
while(cur){
[cur.next,pre,cur] = [pre,cur,cur.next]
}
return pre
};
复制代码
分析 递归
- 链表初始化状态,由于是递归可以从最后一位反推反转过程
- 由于最后一个节点指向下一个节点为空不存在下下个节点所以直接返回当前节点。
- 从倒数第二个节点开始分析将当前节点
head
下一个的下一个节点head.next
指向当前节点head
,将当前节点指向null
。
重复执行...
最后整个链表就反转过来了
总结 递归
- 首先定义
pre
指针当前节点的下一个节点反转后的节点 - 由于后续需要用到
head
当前节点以及head.next
,使用需要判断head
当前节点是否为null
、head.next
是否存在。 - 不断递归一次处理,
head.next
的下一个节点指向当前节点,并断开当前节点与的下一个节点的联系也就是说变为null
。
代码实现 递归
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(!head || !head.next) return head
let pre = reverseList(head.next)
head.next.next = head
head.next = null
return pre
};
复制代码