反转链表
1. 非递归解法:
解题思路:
- 定义三个指针: cur , p1 p2, cur与p1为了完成指针逆指, p2保存下一个应当逆转的节点,防止迷路
- 每次让 p1 的next 指向 cur,实现一次局部反转
- 局部反转完成之后,cur p1和 p2 同时往前移动一个位置
- 循环上述过程,直至 p1到达链表尾部
思路图解:

代码实现:
var reverseList = function(head) {
if(!head) return null
let cur = null
let p1 = head
let p2 = head.next
while(p1) {
p1.next = cur
cur = p1
p1 = p2
p2 = p2 ? p2.next : null
}
return cur
};
2. 递归解法:
递归解法可能有点绕,这里进行详尽说明:
解题思路:
终止条件就是链表为空,或者是链表没有尾结点的时候,直接返回
if (head == null || head.next == null)
return head;
递归调用是要从当前节点的下一个结点开始递归。逻辑处理这块是要把当前节点挂到递归之后的链表的末尾
代码实现:
function reverseList(head) {
//终止条件
if (head == null || head.next == null)
return head;
//保存当前节点的下一个结点
let next = head.next;
//从当前节点的下一个结点开始递归调用
let reverse = reverseList(next);
//reverse是反转之后的链表,因为函数reverseList
// 表示的是对链表的反转,所以反转完之后next肯定
// 是链表reverse的尾结点,然后我们再把当前节点
//head挂到next节点的后面就完成了链表的反转。
next.next = head;
//这里head相当于变成了尾结点,尾结点都是为空的,
//否则会构成环
head.next = null;
return reverse;
}
因为递归调用之后head.next节点就会成为reverse节点的尾结点,我们可以直接让head.next.next = head;这样代码会更简洁一些,看下代码
function reverseList(head) {
if (head == null || head.next == null)
return head;
let reverse = reverseList(head.next);
head.next.next = head;
head.next = null;
return reverse;
}