反转链表
| Category | Difficulty | Likes | Dislikes |
|---|---|---|---|
| algorithms | Easy (63.04%) | 512 | - |
Tags
Companies
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
/*
* @lc app=leetcode.cn id=206 lang=javascript
*
* [206] 反转链表
*/
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
};
1
一般链表的题我们会使用三个变量
prevcurnext
具体的使用我们就在这道里讲,最后再总结

反转后链表的的区别只在于每个节点的next发生了改变。
作为尾节点的
next必然是指向NULL的
既然是每个节点指向前继节点,作为链表的首位前继既然是无节点的,为了统一,我们会给链表前添加一个节点NULL
我们把前继节点称为prev,我们此时要操作的节点为cur,这里指上图的1,所以有

let prev = null
let cur = head
按上面说的,倒序只不过是把当前节点的next改为前继节点,所以有

cur.next = prev
此时,就会遇到一个问题,我们无法操控原本的老链表了,所以我们需要next,用来标记原本cur的next,所以有

let next = cur.next
只要我们不断重复上面的操作,左表的链表就是老链表的倒序了
为了回到"原本"的位置,我们要让prev和cur老链表的“头节点”去,所以有

cur = next
prev = cur
小总结一下,我们在一个循环中,应该做哪些事
-
为了统一,假设
cur前有有一个前继节点,即prev:prev = null -
在操作
cur改变其next指点,缓存下一个节点:next = cur.next -
开始操作
cur,使其指向前继节点cur.next = prev -
让
cur和prev回到"原本"的位置prev = curcur = next
注意这里的顺序是不能颠倒的
我们只要循环上述步骤1~3即可以倒序完整个链表,而停止的条件就是cur为NULL时

while (cur) {
next = cur.next
cur.next = prev
prev = cur
cur = next
}
最后我们只要返回prev就是可以了,所以全部代码为
var reverseList = function (head) {
let [prev, cur, next] = [null, head, null]
while (cur) {
next = cur.next
cur.next = prev
prev = cur
cur = next
}
return prev
};
2 利用ES6新特性
这道题难的不是写不出,难的是代码要写的优雅点
在上面我们使用了三个变量
prevcurnext
这个next的作用只是一个缓存,比如我们在进行两数交换的时候,如下
let a = 1
let b = 2
let temp = a
a = b
b = temp
console.log(a); // 2
console.log(b); // 1
上面代码中的temp就和我们使用next的本质是一样的:缓存
现在我们来看下面这段代码
let a = 1
let b = 2;
[a, b] = [b, a]
console.log(a); // 2
console.log(b); // 1
注意:因为第3行代码也是一个表达式,所以要在第2行代码后面添加
;不然会报语法错误
我们在不使用temp变量缓存的情况下,就完成了两数交换,原因是这种语法帮我们做了缓存:
在赋值前,会把右边表达式变量存储的值先取出来,然后再进行赋值.

那根据这种写法,我们再来思考原本的代码
var reverseList = function (head) {
let [prev, cur, next] = [null, head, null]
while (cur) {
next = cur.next
cur.next = prev
prev = cur
cur = next
}
return prev
}
那我们就可以不使用next
- 当前节点的
next指向前继节点:cur.next = prev cur和prev往后移动一位,操作新的“头”节点prev = curcur = cur.next
var reverseList = function (head) {
let [prev, cur] = [null, head]
while (cur) {
[cur.next, prev, cur] = [prev, cur, cur.next]
}
return prev
};