- 题目
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
}
}
- 解题关键
- 基本情况:
if (head.next == null) return head;
- 返回值如何处理才能串联成合适的逻辑。
具体: 递归过程可以看作从蓝色 -> 橙色 -> 黑色 -> 绿色 -> 红色
链表反转递归到底的情况:4节点将成为头节点。用3,4,null的视图来看。
head.next.next = head;
head.next = null; // 断开原来连接
完成链表反转后,4也就成为了头节点。返回值应该是上层的head.next;
对应的代码可以到:
public ListNode reverseList(ListNode head) {
if (head.next == null) return head;
// 反转逻辑
head.next.next = head;
head.next = null;
// 可以发现,head.next再上一步已经修改,于是在反转逻辑之前需要多一个引用来存储上层的head.next
// return (上层的head.next);
}
进一步:
public ListNode reverseList(ListNode head) {
if (head.next == null) return head;
// 新增应用存储head.next;
ListNode ret ; // 该引用需要递归完成,每一次执行该函数都会用到,具体职责有两个,见下文
// 反转逻辑
head.next.next = head;
head.next = null;
return ret;
}
进一步:新增引用存储递归到底的head.next,该引用同时还是递归调用的核心,具体职责:
- 保留递归到底的head.next,一直返回至应用层,本例就是val = 4的节点,所有递归都不会改变ret的值。
- 若未找到递归到底的情况,把head.next都压入系统栈。只要下层完成反转,上层才开始反转。
间接实现对节点顺序访问倒叙操作。
1 -> 2 -> 3 -> 4 -> null
1 -> 2 -> 3 <- 4 ret == 4
1 -> 2 <- 3 <- 4 ret == 4
null <-1 <- 2 <- 3 <- 4 ret == 4
值得注意的是
head.next = null;
// 在最上层调用中也返回后,1 -> 2 变为 1 -> null;
// 不仅是断开原来连接,还成功将原本头节点反转成尾节点
public ListNode reverseList(ListNode head) {
if (head.next == null) return head;
// 新增应用存储(不变的)头节点并完成递归
ListNode ret = reverseList(head.next);
// 反转逻辑
head.next.next = head;
head.next = null;
return ret;
}
- 空值处理,传入的head为NULL,返回本身;代码完成
public ListNode reverseList(ListNode head) {
if ( head == null || head.next == null) return head;
// 新增应用存储head.next并完成递归
ListNode ret = reverseList(head.next);
// 反转逻辑
head.next.next = head;
head.next = null;
return ret;
}
- 测试用例
public static void main(String[] args) {
Solution s = new Solution();
ListNode head = s.initListNode(1);
head.buildNext(2).buildNext(3).buildNext(4);
// Solution2.printList(head);
ListNode newHead = s.reverseList(head);
// Solution2.printList(newHead);
}
private ListNode initListNode(int i) {
return new ListNode(i);
}
private ListNode buildList(ListNode head, int i) {
if (head == null) {
throw new IllegalArgumentException("头节点不允许为空");
}
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}
return cur.next = new ListNode(i);// 返回新增的节点的指针
}
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
private ListNode buildNext(int i) {
return new Solution().buildList(this, i);
}
}
时间复杂度:O(n),空间复杂度:O(1)
- 拓展
链表反转迭代解法见:
https://blog.csdn.net/chenghan_yang/article/details/94835745