声明:该题是leecode206
题目
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
链表的数据结构如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
}
}
迭代法
迭代法,算法的核心,就是在每一次迭代的时候,将相邻的两个节点之间的指针进行反转。
我们来看一次反转,需要做哪些事情。
假设我们当前节点是1,
ListNode current = head;
我们要将1.next指向它的前一个节点,现在1的前一个节点是空,我们设
ListNode prev = null;
我们把 1.next = prev = null。但当我们这么做的时候,整个单向链表就断了,1后面的元素就找不到了,所以在这之前,我们需要一个额外的变量来存储原来 1.next 的值。
ListNode next = current.next;
current.next = prev;
这样,我们就完成了对1的修改,那我们的一次迭代结束了么,还没有,
我们还需要将current指针往下移动,让它指向下一个节点。
current = next;
但当我们将current指向2的时候,下一次迭代,2.next需要指向1,但是这个时候,我们找不到1,因为没有变量引用1。所以在将current指向2之前,我们还需要先将1的引用赋值给prev,让它指向1。
prev = current;
current = next;
那迭代在什么情况下结束呢?
current刚开始指向1,然后迭代着指向2、指向3、指向4、指向5,
是不是当current变量指向null的时候,迭代就结束了,这个时候的prev,就是我们反转后新的链表的头节点。
完整代码如下
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode current = head;
ListNode prev = null;
while (current != null) {
// 1、暂存当前节点next引用变更前的后续节点,防止链表丢失
ListNode next = current.next;
// 2、将前一个节点的引用赋值给当前节点的next
current.next = prev;
// 3、将当前节点赋值给prev变量
prev = current;
// 4、将当前节点指针往下迭代
current = next;
}
return prev;
}
}
递归法
其实递归法跟上面的迭代法是如出一辙的。我们看上面的迭代法,其中有两个变量,是特别重要。
一个是current,它指向当前节点,然后在每一次迭代后,指向下一个节点;
一个是prev,它指向当前节点的上一个节点,然后在每一次迭代后,指向当前节点。
就是这种变换,给了我们层层往下递归创造了条件。
那我们思考一下,递归的结束条件是什么?
是不是也是当 current == null 的时候,递归就结束了,这个时候的头节点,不就是 prev么?
递归代码呼之欲出:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
// 初始的prev节点是空
return recursion(null, head);
}
public ListNode recursion(ListNode prev, ListNode current) {
if (current == null) {
return prev;
} else {
// 1、暂存当前节点next引用变更前的后续节点,防止链表丢失
ListNode next = current.next;
// 2、将前一个节点的引用赋值给当前节点的next
current.next = prev;
// 3、将当前节点赋值给prev变量
prev = current;
// 4、将当前节点指针往下迭代
current = next;
// 5、递归进行指针变换
return recursion(prev, current);
}
}
}