函数递归就是函数自己调用自己的体现,我们称之为递归函数。它的有点就是用有限的函数来定义实现对象无限集合,缺点就是递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多是速度要比循环慢的多。一般而言,但凡能够被迭代(循环)解决的问题,递归都可以
递归的原理:通常把一个大型的复杂的问题层层转换成与原来问题相似的规模比较校的问题来解析。这样可以减少代码量。
学习递归函数,我们就要知道它的三个必要条件:
- 前进段:指的就是讲问题从大化小
- 结束段:问题无法再继续化小,则处理当前的问题
- 返回段:将小问题处理完毕之后,向上返回(有些问题是不需要返回的)
递归函数的执行流程:当达到结束段条件,递归返回,当没有达到递归的结束段,递归继续。
例如:求1+2+3+…+100的和
分析:1+2+3+…+100可以看成100加到1,这样可以调用本身1;可以避免1加到100这种顺序临界值不好引入,带来的麻烦和计算错误。
100+99+98+97…+1
n+(n-1),一直到1
public static int f(int n){
//结束条件
if(n==1){
return 1;
}
return n+f(n-1);/* 1~100的和的表达式 */
}
public static void main(String[] args) {
System.out.println(f(100));//結果5050
}
问题2:斐波那契数列 1 1 2 3 5 8 13 21 34 55 …
分析:f(n)=f(n-1)+f(n-2),其中,f(n)指的是数列的第n项,f(1)=1,f(2)=1
例如f(5),我们可以拆分成下图
代码段为
public static int fibo(int n){
if(n==1||n==2){
return 1;
}
return fibo(n-1)+fibo(n-2);
}
其实这道题我们也可以通过迭代来做,如下
public static void fibi(int n){
int a = 1;
int b = 1;
System.out.println(a);
System.out.println(b);
int count = 2;
int c;
while(ture){
c = a + b;
System.out.println(b);
count++;
if(count = n){
return;
}
a = b;
b = c;
}
问题3:汉诺塔
汉诺塔是一个发源于印度的益智游戏,也叫河内塔。相传它源于印度神话中的大梵天创造的三个金刚柱,一根柱子上叠着上下从小到大64个黄金圆盘。大梵天命令婆罗门将这些圆盘按从小到大的顺序移动到另一根柱子上,其中大圆盘不能放在小圆盘上面。当这64个圆盘移动完的时候,世界就将毁灭。 那么好多人会问64个圆盘移动到底会花多少时间?那么古代印度距离现在已经很远,这64个圆盘还没移动完么?我们将通过递归算法来计算来看看要完成这个任务到底要多少时间?
接下来我们来进行简单的图示(3个盘子)
x y z代表三根柱子,矩形代表3个盘子,此时需要将x上的三个盘子移动到z上,即X->Z,
- 先将第一个从X移到Z,X->Z
2. 再将第二个从X移到Y,X->Y
3. 再将第一个从Z移到Y,Z->Y
4. 将第三个从X移到Z,X->Z
5. 先将第一个从Y移到X,Y->X
6. 再将第二个从Y移到Z,Y->Z
7. 再将第一个从X移到Z,X->Z
class Hanno{
public static void main(String[] args){
//盘子的个数 出发 中间 目的
hanno(3,"X","Y","Z");
}
public static void hanno(int n,String begin,String mid,String end){
if(n==1){
System.out.println(begin+" -> "+end);
}else{
hanno(n-1,begin,end,mid);//第二个盘子从x出发,目的地是y
System.out.println(begin+" -> "+end);
hanno(n-1,mid,begin,end);//前两个盘子,从y到z
}
}
}
此题的解题思路是将三个盘子拆分成2组,将前两个看成一个,第三个看成一个,再将前两个解决,要把3个从X移到Z,先得把前两个从X 移到 Y,再把第三个从X移到Z,最后再把前两个从Y移到Z即可。
同理,64个也是一样,将64个分成两组,前63个为一组,第64个是一组再前63个盘子这样分,直到一个盘子为止