# 反转链表(206)
# 题目
反转一个单链表。
# 示例
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
# 进阶
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
# 算法
# 迭代
声明一个头节点listHead
,然后依次向后遍历原链表,将当前节点插入到listHead
和listHead.next
之前,最后返回listHead.next
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const reverseList = (head) => {
let listHead = new ListNode();
while (head) {
let nextNode = head.next;
head.next = listHead.next;
listHead.next = head;
head = nextNode;
}
return listHead.next;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 递归
每一次递归都将下一个节点传入reverseList(head.next)
,当当前节点head
等于null
(为了判断是否是空链表)或者当前节点的下一个节点为null
时,结束递归
对于任意一个节点,我们首先能拿到上一次递归返回的节点node
,我们希望当前节点head
的下一个节点指向当前节点head
,所以将当前节点head
赋值给head.next.next
此时head.next
的指向需要被改变,因为上一步已经将head.next
的next
指向了当前节点head
,如果此时head
的next
还是指向下一个节点就会造成死循环,所以我们将head
的下一个指向null
最后完成当前节点head
的操作后我们返回节点node
,这里的node
始终上一次递归返回的node
,所以node
没有发生变化,一直是最深一次递归返回的head
,所以最后结束函数返回的就是原链表的尾节点(翻转后链表的头节点)
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const reverseList = (head) => {
if (head === null || head.next === null) {
return head;
}
let node = reverseList(head.next);
head.next.next = head;
head.next = null;
return node;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 双指针
维护两个相邻的指针,快指针是prev
(默认指向head
),慢指针是cur
(默认指向null
),将prev.next
指向cur
(即每次都翻转prev
和cur
之间的指向关系),然后都向后移动一位并重复之前的翻转,最后当prev
指向null
时返回cur
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const reverseList = (head) => {
let prev = head,
cur = null;
while (prev) {
let nextNode = prev.next;
prev.next = cur;
cur = prev;
prev = nextNode;
}
return cur;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 双指针II
有两个指针start
和toEnd
,开始都指向头节点head
,start
表示每一次操作后的链表的头部(最后返回的也是这个链表头),toEnd
最后会指向null
,每一次操作重复下面的过程:
- 将
toEnd.next
指向的节点指向start
- 将
toEnd.next
指向(上述改变前的)toEnd.next.next
- 将
start
指向(上述改变前的)toEnd.next
最后当toEnd
指向null
时返回start
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const reverseList = (head) => {
if (!head) return null;
let toEnd = head,
start = head;
while (toEnd.next) {
let nextNode = toEnd.next;
toEnd.next = toEnd.next.next;
nextNode.next = start;
start = nextNode;
}
return start;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19