递归总结
定义
递归
递归是一种在程序设计语言中广泛应用算法。一种编程思想和技巧。 其主要特点就是通过反复调用自身函数来解决问题。
递归函数
直接或间接调用自身的函数称为递归函数。它通常把一个大型复杂的问题层层转化成一个与原问题相似的规模较小的问题来求解。
递归基本思想
- 将问题分解:
把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的小问题,最小问题可以直接解决。 - 递归的关键在于找出递归定义和递归终止条件。
递归定义:使问题向边界条件转化的规则。递归定义必须能使问题越来越简单。
递归终止条件:也就是所描述问题的最简单情况,它本身不再使用递归的定义。 - 在重复中找变化,在变化中找重复
递归的三大要素
第一要素——明确你这个方法要干什么
对于递归,定义一个方法时,首先要清楚这个方法的功能是什么,而这完全由你自己来定义。也就是说,先不管方法里面的代码是什么,先弄明白这个方法是用来干什么就可以了。
第二要素——寻找递归结束条件
递归就是在方法内部调用这个方法本身,所以,我们必须要找出递归的结束条件,不然会一直调用自己,进入死循环。也就是说,我们需要找出当参数为多少时,递归结束,之后直接把结果返回(注意:这个时候我们必须能根据这个参数,直接知道方法的结果是什么)。
第三要素——找出函数的等价关系式(递推公式)
第三要素就是,不断缩小参数的范围,但要保持原函数的结果不变。
递归算法设计步骤
- 找重复(将问题转化为子问题)
分析问题、寻找递归:找出大规模问题与小规模问题的关系,这样通过递归使问题的规模逐渐变小。 - 找重复中的变化量(即递归的参数)
- 找参数的变化趋势(设计递归的出口)
找出停止条件,即算法可解的最小规模问题。 - 设计递归函数。
通常解决递归算法的思路
- 切蛋糕思维(问题分解)
- 如果不能切,思考递推公式和等价转换
如何练习,提高设计递归函数的能力?
- 循环改递归(循环和递归,基本都可以相互转化)
- 学习经典递归
- 大量练习,总结规律,掌握套路
- 寻找感觉,挑战高难度算法
常见的递归题解
情况一:函数本身可以实现递归
1.求n的阶乘
递归解题思路
n!=1×2×3×…×n
阶乘定义:0!=1,n!=(n-1)!×n
f1(n):求n的阶乘——>f1(n-1):求(n-1)的阶乘
- 找重复:n*(n-1)的阶乘,求n-1的阶乘是原问题的重复(规模更小),即转换为子问题
- 找变化:变化的量作为参数
- 找边界:出口(防止死循环,导致栈溢出)
递归解题
int f1(int n){
if(n==1){
return 1;
}
return n*f1(n-1);
}
2.打印数组i-j的元素
递归解题
void f2(int i,int j){
if (i>j){
return;
}
System.out.print(i);
f2(i+1,j);
}
情况二:函数本身不是变化的,需要借助另外的参数实现递归
3.对arr数组元素求和
思路
已经不能将原有的方法直接实现递归(数组本身是不会变化的,所以不能做递归的变化参数),所以需要借助参数。这里将每次递归的数组起点索引作为变化参数,每递归一次,索引起点+1。
递归解题
static int sumArr(int[] arr,int begin){
//两个判断边界,效果相同
if(begin==arr.length){
return 0;
}
// if (begin==arr.length-1){
// return arr[begin];
// }
return arr[begin]+sumArr(arr,begin+1);
}
4.翻转字符串
思路
每次只记录字符串的最后一位,将最后一位作为递归变化的参数
递归解题
String reverse(String s,int end){
if(end==0){
return s.charAt(end)+"";
}
return s.charAt(end)+reverse(s,end-1);
}
情况三:不能将问题直接转化为子问题,需要借助递推公式和等价转换
5.斐波那契数
思路
每一项都是前两项的和
示例:1 1 2 3 5 8 13 ……
递推公式:f(n)=f(n-1)+f(n-2)
递归解题
int fib(int n){
if (n==1||n==2){
return 1;
}
return fib(n-1)+fib(n-2);
}
6.求最大公约数
思路
m%n=0 n是两数的最大公约数
若m%n=k,f(m,n)=f(n,m%n)
递归解题
int gcd(int m,int n){
//直到n=0,求得公约数为m
if (n==0){
return m;
}
return gcd(n,m%n);
}
2021.02.17更新
关于递归的深入理解可参考文章(感觉讲的非常不错,通俗易懂):什么是递归,通过这篇文章,让你彻底搞懂递归