1 单链表
对于单链表讲,单链表中的结点不一定存储在相邻位置,一个结点储存两个信息,一是该节点的值,二是指向下一个结点的位置信息。
// 单链表节点的结构
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x; }
}
本文的主要目的是以单链表出发,递归实现反转单链表——>反转链表前N个结点——>反转链表的一部分
2 递归实现反转单链表(LetCode 206)
这个算法可能很多读者都听说过,这里详细介绍一下,先直接看实现代码:
ListNode reverse(ListNode head) {
if( head == null || head.next == null) return head;
ListNode last = reverse(head.next);
head.next.next = head;
head.next = null;
return last;
}
下面来详细解释一下这段代码。
首先(大体出现链表反转的结果):
对于递归算法,最重要的就是明确递归函数的定义。具体来说,我们的reverse函数定义是这样的:
输入一个节点head,将「以head为起点」的链表反转,并返回反转之后的头结点。
明白了函数的定义,再来看这个问题。比如说我们想反转这个链表:
那么输入reverse(head)后,会在这里进行递归:
ListNode last = reverse(head.next);
不要跳进递归(你的脑袋能压几个栈呀?),而是要根据刚才的函数定义,来弄清楚这段代码会产生什么结果:
按照定义,这个reverse(head.next)执行完成后,整个链表应该变成了这样:
并且根据函数定义,reverse函数会返回反转之后的头结点,我们用变量last接收了。
然后(指针进行修正上下结点):
现在再来看下面的代码:
head.next.next = head; //修正上结点——将head的地址赋予元素2的地址(即链表2后面指向1)
接下来进行的操作:
head.next = null; // 修正下结点
return last;
最后(递归结束边界base case):
if (head.next == null) return head;
**小小总结下
大体可以分为以下三步骤:
- 对于递归问题,我们一定要知道递归的定义(递归后长怎么样的?)
- 对于递归后的链表修改上下结点的(位置)指向
- 明白递归的终止条件(basecase)——结点指向下一个位置为null
理解了这两点后,我们就可以进一步深入了,接下来的问题其实都是在这个算法上的扩展。
3 反转链表前N个结点
首先看下大概的过程:
代码实现如下:
ListNode tem = null; // 后驱结点(用来修改——反转后中 返回结点的指向!)
ListNode reserveN(ListNode head, int n){
// 定义递归函数:反转链表的前n个结点
if(n == 1){
tem = head.next;
return head;
}
// 以 head.next 为起点,需要反转前 n - 1 个节点
ListNode last = reseveN(head.next, n-1);
head.next.next = head;
// 让反转之后的 head 节点和后面的节点连起来
head.next = tem;
return last;
}
小小总结下反转链表前N个结点
对比第一个反转链表,大体的思路差不多,都是
- 定义递归方程(明白递归反战后是长怎么样的?)
- 对于递归后的链表修改上下结点的(位置)指向
- 明白递归的终止条件(basecase)——结点指向下一个位置为null
但是相比较第一个,这里重点关注结束条件——n,和返回结点的指向(第一个是指向null,这个是指向第n个结点的下一个)
4 反转链表的一部分(LetCode 92)
问题:给一个索引区间[m,n](索引从 1 开始),仅仅反转区间中的链表元素。
ListNode reverseBetween(ListNode head, int m, int n){
// base case
if (m==1){
return reverseN(head, n);
}
// 前仅到反转的起点触发 base case
head.next = reverseBetween(head.next, m-1, n-1);
return head;
}
核心关注点是:边界状态调用链表中的前N个结点
总结
递归强调三步骤:
- 定义递归方程(递归后长怎么样的?)
- 递归直接调用返回(脑子别压栈!)
- 明白递归终止条件(basecase)
参考:
https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/bu-bu-chai-jie-ru-he-di-gui-di-fan-zhuan-lian-biao/