递归魔法:反转单链表
1、递归反转整个链表
力扣第206题,反转链表
[206]反转链表
/**
* 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 {
// 该函数的意思是,返回当前头节点为head,反转后的新的链表的头节点
public ListNode reverseList(ListNode head) {
// base case
if (head == null || head.next == null) {
return head;
}
// 拿到当前节点的下个节点的反转后的头节点
ListNode last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
}
}
这个样子的递归我个人觉得很有意思,巧妙之处在于这两行代码:
head.next.next = head;
head.next = null;
可能有图更好理解:
- 但是还是需要写一下利用指针进行反转单链表的代码
[206]反转链表
/**
* 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 {
// 该函数的意思是,返回当前头节点为head,反转后的新的链表的头节点
public ListNode reverseList(ListNode head) {
// base case
if (head == null || head.next == null) {
return head;
}
ListNode pre = head, cur = head, next = head.next;
head.next = null;
while (next != null) {
cur = next;
next = next.next;
cur.next = pre;
pre = cur;
}
return cur;
}
}
2、反转链表前N个节点
关键点在于需要一个successor记录后驱节点:
ListNode successor;// 记录后继节点
// 反转以 head 为起点的 n 个节点,返回新的头节点
public ListNode reverseN(ListNode head, int n) {
// base case变成 n==1
if (n == 1) {
successor = head.next;
return head;
}
ListNode last = reverseN(head.next, n - 1);
head.next.next = head;
head.next = successor;
return last;
}
3、反转链表的一部分
力扣第92题,反转链表Ⅱ
给定一个索引区间[m,n](索引从1开始),仅反转区间中的链表元素
[92]反转链表 II
/**
* 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 {
// 题目等效以第left为头节点,反转前(right-left+1个)节点
// 该函数的意思是,以head为头节点,反转[left,right]之间的节点,返回新的头节点
public ListNode reverseBetween(ListNode head, int left, int right) {
// base case
if (left == 1) {
// 相当于反转前n个节点
return reverseN(head, right);
}
// 递归到新的链表上,保证元素对应位置相同
head.next = reverseBetween(head.next, left - 1, right - 1);
return head;
}
ListNode successor;// 后继节点
// 返回反转头节点为head,反转前n个节点后的头节点
ListNode reverseN(ListNode head, int n) {
// base case
if (n == 1) {
successor = head.next;
return head;
}
ListNode last = reverseN(head.next, n - 1);
head.next.next = head;
head.next = successor;
return last;
}
}