链表第二篇,前篇可见: 「leetcode」141-环形链表(两种解法&JS实现的注意点)
题目
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re…
思路分析
- 下面有个官方提示:链表可以选用迭代或递归方式完成反转
迭代方法
- 一开始我的思路是遍历一遍链表,然后将其一一反转,但是这样需要O(2N)的时间复杂度,所以 ×
- 那么我们可以边遍历边反转,也即是遍历一遍,将当前的指针的next指向上一个,就可以了。这样只需要O(N)的时间复杂度。
/**
* 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 cur = head // 当前
let last = null // 上一个节点的地址
let origin = null // 原本的指向
let endPoint = null // 最终输出的链表的起点
// 这里的origin可以不用闭包,用临时变量解决
while (cur) {
origin = cur.next
cur.next = last
last = cur
cur = origin
}
endPoint = last
return endPoint
};
- 这里要额外注意返回的是什么,不要真的把链表当数组处理。应该返回的是链表的最后一个节点的指针。
递归方法
- 递归这里我看了官方解法,按照自己的理解来描述一下。
- 首先要做一个递归解法的话,返回的应该是自己的调用,这样才能保证到达最后一个节点。
- 思路很简单描述,例如 4->5->null,那么反转的话就是让4<-5,也就是4的next(5)的next由null变为4,为了防止死循环,再让4的next先解开为null,4成为最后一个节点(fake),再重复进行这个过程。
- 但是这里为什么最终返回的是 newHead 而不是 head, 我也不是很清楚,如果有知道的大佬希望可以在评论区讨论下,先感谢了。
// 递归解法
var reverseList = function(head) {
if (!head || !head.next) return head
// 递归传入下一个节点,目的是为了到达最后一个节点
let newHead = reverseList(head.next)
head.next.next = head
head.next = null
return newHead
};