反转整个链表

反转链表函数 reverse 定义:输入一个结点 head,将 以 head 为起点 的链表反转,并返回反转之后的头结点

假设需要反转链表:
image.png
递归算法基础框架:

  1. public ListNode reverse(ListNode head) {
  2. ListNode last = reverse(head.next);
  3. return last;
  4. }

代码 reverse(head.next);的效果是什么呢?
image.png

但是我们最终期望的结果是:
image.png

怎么才能变成最终期望的结果呢?

第一步:让 head 节点的下一个节点的 next 指针从指向 null 变成指向 head 节点
image.png
第二步:让 head 节点的 next 指针指向 null
image.png
递归算法框架:

  1. public ListNode reverse(ListNode head) {
  2. ListNode last = reverse(head.next);
  3. // 让 head 节点的下一个节点的 next 指针从指向 null 变成指向 head 节点
  4. head.next.next = head;
  5. // 让 head 节点的 next 指针指向 null
  6. head.next = null;
  7. return last;
  8. }

那递归结束条件是什么呢?
如果 head 是空节点,那么肯定递归就结束了。
特别需要注意的是,如果链表只有一个节点,那么也无需进行反转,递归也可以结束
完整地递归算法:

  1. public ListNode reverse(ListNode head) {
  2. if (head == null || head.next == null) {
  3. return head;
  4. }
  5. ListNode last = reverse(head.next);
  6. // 让 head 节点的下一个节点的 next 指针从指向 null 变成指向 head 节点
  7. head.next.next = head;
  8. // 让 head 节点的 next 指针指向 null
  9. head.next = null;
  10. return last;
  11. }

反转链表前 N 个节点

那么如果只是想反转链表前 N 个节点呢:
image.png

  1. // head 的后驱节点
  2. ListNode successor = null;
  3. // 以 head 为起点,需要反转前 n 个节点
  4. public ListNode reverseN(ListNode head, int n ) {
  5. if (n == 1) {
  6. // 记录第 n + 1 个节点
  7. successor = head.next;
  8. return head;
  9. }
  10. // 以 head.next 为起点,需要反转前 n - 1 个节点
  11. ListNode last = reverseN(head.next, n - 1);
  12. // 让 head 节点的下一个节点的 next 指针从指向 null 变成指向 head 节点
  13. head.next.next = head;
  14. // 让 head 节点的 next 指针指向 successor
  15. head.next = successor;
  16. return last;
  17. }

反转链表的一部分

那么如果只是想反转链表部分节点呢:
image.png

  1. ListNode successor = null;
  2. public ListNode reverseBetween(ListNode head, int m, int n) {
  3. if (m == 1) {
  4. // 相当于反转前 n 个节点
  5. return reverseN(head, n);
  6. }
  7. // 前进到反转的起点
  8. head.next = reverseBetween(head.next, m - 1, n - 1);
  9. return head;
  10. }
  11. // 以 head 为起点,需要反转前 n 个节点
  12. public ListNode reverseN(ListNode head, int n ) {
  13. if (n == 1) {
  14. // 记录第 n + 1 个节点
  15. successor = head.next;
  16. return head;
  17. }
  18. // 以 head.next 为起点,需要反转前 n - 1 个节点
  19. ListNode last = reverseN(head.next, n - 1);
  20. // 让 head 节点的下一个节点的 next 指针从指向 null 变成指向 head 节点
  21. head.next.next = head;
  22. // 让 head 节点的 next 指针指向 successor
  23. head.next = successor;
  24. return last;
  25. }