翻转链表
- LeetCode题目链接
- 卡尔老师代码随想录讲解
- 关键点: 这道题目没有要求空间,所以我第一次做的时候立马想到用一个数组保存指向每一个元素的指针,然后再遍历数组依次改变节点指针指向,但这样无疑增加了额外的空间开销和时间。所以根据卡尔老师所讲我们可以使用双指针的方法来翻转链表,一快一慢,每次指向两个相邻元素进行翻转。所以也可以考虑递归方法。
- 代码:
非递归写法:
var reverseList = function(head) {
let prev = null
let cur = head
while (cur) {
let tmp = cur.next
cur.next = prev
prev = cur
cur = tmp
}
return prev
};
递归写法:
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverse = function (prev,cur) {
//链表处理完毕应该返回指向最后一个节点的指针
if (!cur) return prev
let tmp = cur.next
cur.next = prev
return reverse(cur,tmp)
}
var reverseList = function(head) {
let prev = null
let cur = head
return reverse (prev,cur)
};
暴力解决方法:
var reverseList = function(head) {
let parr = []
let search = head
while (search) {
//保存每个指向节点的指针,越靠后节点的指针在数组中越前
parr.unshift(search)
search =search.next
}
if (parr.length !=0){
//如果非空链表,设置节点的next,翻转链表
for (let i = 0; i < parr.length ;i++) {
parr [i].next =((i+1) < parr.length ? parr [i+1] : null)
}
head = parr[0]
}
return head
};
- 注意:
- 修改 cur.next 前要用临时指针保存next 节点
- cur 和 prev 的修改顺序
- 递归写法可以参照非递归写法,这样更加清晰过程
- 时间复杂度分析:
时间:O( n n n),因为每个元素都只被访问两次所以为 2 n 2n 2n,对于暴力解决为 3 n 3n 3n,所以数量级都为 n n n
空间:非递归和暴力都为O( 1 1 1),递归为O( n n n)