携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
题目(Reverse Linked List)
链接:https://leetcode-cn.com/problems/reverse-linked-list
解决数:9798
通过率:73.2%
标签:递归 链表
相关公司:bytedance amazon microsoft
给你单链表的头节点 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
进阶: 链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
思路
迭代
- 关键
- 将当前节点的指针指向上一个节点
- 然后更新当前节点和下一个节点的值即顺移
- 技巧
- 设置哨兵节点 null,初始化时将head节点指向null,下一步将next指向head
- 重复以上动作直到当前节点为尾节点的节点null
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let prev = null;
let curr = head;
while(curr != null){
let next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
};
尾递归
- 其实就是解法一的简化版
-
prev = curr;
curr = next;
-
- 此解法将 上面放在递归里返回
- 同理都是做将当前节点指向前一个节点的操作之后,来顺移更新前一个、当前、和下一个节点的操作
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let reverse = (prev,curr) => {
if(!curr)return prev;
let next = curr.next;
curr.next = prev;
return reverse(curr,next);
}
return reverse(null,head);
};
递归
- 关键是反转操作
- 当前节点 head,下一个节点 head.next
- head.next.next = head
- 此处将原 head.next 指向head,即是反转
- head.next = null
- 此处将原 head 指向head.next的指针断开
- 递归
- 由编译器函数调用执行栈原理可知
- 最先调用的函数会在递归过程中最后被执行,而最后调用的会最先执行
- 因此此题,最先返回最后两个节点开始反转操作
- 依次从后面两两节点开始反转
- 由编译器函数调用执行栈原理可知
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
// 如果测试用例只有一个节点 或者 递归到了尾节点,返回当前节点
if(!head || !head.next) return head;
// 存储当前节点的下一个节点
let next = head.next;
let reverseHead = reverseList(next);
// 断开 head ,如图闪电⚡️标记处
head.next = null;
// 反转,后一个节点连接当前节点
next.next = head;
return reverseHead;
};
栈解
- 既然是反转,那么符合栈先进后出的特点
- 将原节点依次入栈
- 出栈时,重新构造链表改变指向
- 同样设置哨兵节点
- 最后返回哨兵的next即为所求
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let tmp = head;
let tHead = new ListNode(0);
let pre = tHead;
let stack = [];
while(tmp){
stack.push(tmp.val);
tmp = tmp.next;
}
while(stack.length != 0){
pre.next = new ListNode(stack.pop());
pre = pre.next;
}
return tHead.next;
};