1. 数据结构
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
2. 递归策略
2.1 思路
递归调用不影响当前节点,即当前节点
n
k
n_{k}
nk 的指针仍然指向原链表的下一节点
n
k
+
1
n_{k+1}
nk+1,而
n
k
+
1
n_{k+1}
nk+1 已经完成反转,变成链表末尾。因此,head.next.next
可以快速定位到反转链表的尾部,即当前节点的移动位置。
ListNode node = reverseList(head.next);
对 n k + 1 , … … , n m n_{k+1}, ……, n_{m} nk+1,……,nm 部分链表进行反转,返回反转链表的头结点;head.next.next = head;
将当前节点移动到链表末尾;head.next = null;
将当前节点的指针置空。
2.2 复杂度
- 时间复杂度 O(n)
- 空间复杂度 O(n):隐式使用递归栈,递归深度为 n n n。
2.3 代码
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode node = reverseList(head.next);
head.next.next = head;
head.next = null;
return node;
}
}
3. 迭代策略
3.1 思路
该思路与头插法类似,每次循环将当前节点插入链表头部,同时更新头节点。
ListNode node = head.next;
暂存下一节点;head.next = pre;
更新当前节点的指针为原头节点;pre = head;
更新头结点为当前节点;head = node;
继续遍历下一节点。
3.2 复杂度
- 时间复杂度 O(n)
- 空间复杂度 O(1)
3.3 代码
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode pre = null;
while (head != null) {
ListNode node = head.next;
head.next = pre;
pre = head;
head = node;
}
return pre;
}
}