算法-递归
一、算法描述
递归算法是一种直接或者间接调用自身函数或者方法的算法。说简单了就是程序自身的调用。
二、算法实质
递归算法就是将原问题不断分解为规模缩小的子问题,然后递归调用方法来表示 问题的解。(用同一个方法去解决规模不同的问题)
三、算法思想
递归算法,顾名思义就是有两个大的阶段:递和归,即就是有去(递去)有回(归来)。
- 递去:将递归问题分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决
- 归来:当你将问题不断缩小规模递去的时候,必须有一个明确的结束递去的临界点(递归出口),一旦达到这个临界点即就从该点原路返回到原点,最终问题得到解决。
过程图解:

四、递归算法使用条件
- 明确递归的终止条件
- 提取重复的逻辑,缩小问题的规模不断递去
- 给出递归终止时的处理办法
五、案例
阶乘
1
2
3
4
5
6public static int recursion(int number) {
if (number == 1) {
return 1;
}
return number * recursion(number - 1);
}力扣(合并两个有序链表)
题目 链接: https://leetcode.cn/problems/merge-two-sorted-lists/description/
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

算法思路
采用递归算法,若l1 || l2 开始即为空链表,不需要操作返回非空链表,否则判断那个链表的头节点对应的值更小,然后递归,决定下一个添加到结果里的节点,如果后续递归中两个链表有一个为空递归结束。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
} else if (l2 == null) {
return l1;
// 排除非空集合
} else if (l1.val <= l2.val) {
// 寻找最小头节点 每次递归节点 寻找插入的位置 每次更新链表 直到有一个值为空 就跳出递归
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l2.next, l1);
return l2;
}
}复杂度分析
- 时间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。因为每次调用递归都会去掉 l1 或者 l2 的头节点(直到至少有一个链表为空),函数 mergeTwoList 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,O(n+m)。
- 空间复杂度:O(n+m),其中 n和 m分别为两个链表的长度。递归调mergeTwoLists 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists 函数最多调用 n+m次,因此空间复杂度为 O(n+m)。
六、个人对于递归的理解(己见)
每次递归都会缩小范围,例如阶乘递归每次程序调用本身时参数就减一,从大规模逐渐减少到最后小规模的结束条件,输入5,每次递归减一 最终返回就是5 4 3 2 1 = 120(最后结束时候返回的结果),缩小到最小范围时候开始计算返回结果,也就是递归终止条件。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 keep初心!

