Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
题目描述
给你单链表的头节点 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
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
题目解释
链表:N1->N2->N3->...->Nk->Nk+1->...->Nm
反链表 Nm->...->Nk+1->Nk->Nk-1->...->N3->N2->N1
解法1 迭代
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。
- 我们先存储next链表,每次循环,head = head.next 逐渐递减链表个数
但是head会变动。所以我们需要一个中间参数next,每次存储head.next,不参与head的变动。
-
用 pre 存储新的链表,每次把head->next 指向pre,即可反转成为当前节点的反转链表。
-
pre = head pre 依旧是最新的链表
- 注意 空链表 或者 只有一个节点的链表 则返回本身
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
//空链表 或者 只有一个节点的链表 则返回本身
if(!head || !head.next){
return head;
}
//反转链表
let pre = next = null;
while(head){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
};
解法2 递归
递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
-
子问题须与原始问题为同样的事,且更为简单;
-
不能无限制地调用本身,须有个出口,化简为非递归状况处理。
我们希望 Nk+1 的下一个节点指向 Nk,而 Nk+1 = Nk->next
所以 Nk->next->next = Nk
需要注意的是 N1 的下一个节点必须为 null 不然就会变成环。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
//空链表 或者 只有一个节点的链表 则返回本身
if(!head || !head.next){
return head;
}
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
};