携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
LeetCode 206:反转链表
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
解题思路
思路一:递归
思路如下:
用递归函数不断反转当前节点head的后继节点next;
分解:
- 使用递归函数,一直递归到链表的最后一个节点,该节点就是反转后的头节点,记作
newHead. - 此后,每次函数在返回的过程中,让当前结点的下一个节点的 next 指针指向当前节点。
- 同时让当前节点的
next指针指向null,从而实现从链表尾部开始的局部反转 - 当递归函数全部出栈后,链表反转完成。
var reverseList = function (head) {
if (head === null || head.next === null) { // 边界情况
return head;
}
const newHead = reverseList(head.next);
head.next.next = head; // 让后面一个节点指向前一个节点
head.next = null; // 将前一个节点的next置为空
return newHead;
};
时间复杂度: O(n) ,其中 n 为链表的长度
空间复杂度: O(n),其中 n 为链表的长度
思路二:迭代
-
准备prev,curr,next三个指针(next其实是一个临时存储使用的变量);
-
在遍历的过程中,让当前指针curr.next指向前一个指针prev;
-
不断让prev,curr,next向后移动,直到curr为null(边界条件)
实现代码如下:
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function (head) {
var prev = null,
curr = head,
next = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
// ES6的解构
// [prev.next, prev, curr] = [prev, curr, curr.next]
}
return prev;
};
时间复杂度: O(n) ,其中 n 为链表的长度
空间复杂度: O(1);
小结:
反转链表的核心代码如下:
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
其中prev节点的next指向curr, curr是当前节点, next其实是一个临时存储使用的变量;
或者使用ES6的解构语法 [prev.next, prev, curr] = [prev, curr, curr.next]