递归
概念:
方法直接或者间接的方式调用自己本身,这样的形式称为递归
递归的三要素:
1、要有边界条件,也就是停止递归的条件;
2、有点像循环,需要给一个前进条件,每次都对条件做出改变,调用执行自己本身,最终达到停止条件;
3、要有递归返回段,要将程序执行的返回值返回。
递归的特性:
反向性:
由于递归调用程序徐需要维护调用栈,而栈具有后进先出的特效,因此递归程序适合满足取反类的需求。在一些比如字符串取反,列表取反等具有奇效。
递推关系:
递归程序可以较明显的发现递推关系,反过来也可以这么说,具有递推关系的问题基本都可以通过递归求解(当然也许有性能更佳的解法,但递归绝对是一种选择)。
递推关系常见问题有杨辉三角、阶乘计算(见本文第五小节)。下一节重点讨论一下递推关系。
什么适合用递归:
具有以下特征的问题可考虑递归求解:
当问题和子问题具有递推关系,比如杨辉三角、计算阶乘等。
具有递归性质的数据结构,比如链表、树、图。
反向性问题,比如取反。
总结:最根本的还是要抓住问题本身是否可以通过层层拆解到最小粒度来得解。
如何使用递归:
1、根据题目需求定义一个方法,然后进行分析,设置参数和返回值的类型;
2、找到边界条件(找到什么时候不递归)
3、写分支条件
if(边界条件){
执行返回段
}else{
执行前进段(调用自己的方法)
}
举个例子:
public class Demo_02 {
n! 1 * 2 * 3 * 4 * 5 = 5!
public static int fun(int n){
//边界的条件
if(n == 1){
return 1;//返回段
}else{
return n * fun(n - 1);//前进段
}
}
public static void main(String[] args) {
int num = Demo_02.fun(5);
System.out.println(num);
}
}
关系图:
再比如经典的斐波那契数列:
1、1、2、3、5、8、13、21、34...
简单说,就是从第三个数开始,每后个数是前两个数的和。
在数学上斐波拉契数列有以下的定义:F(1) = 1, F(2) = 1, F(n) = F(n - 1) + F(n -2)(n >= 3)。
那如何实现呢?试试递归吧。
public class digui {
public static void main(String[] args) {
digui d = new digui();
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt(); // 输入显示到第几个斐波那契数。
for (int i = 1; i <= m; i++) { // 打印一系列的数,当然要用到循环啦;m就是到第几个数,也就是循环次数;i就是进行到第几个数。
System.out.print(d.fibonacci(i) + "\t");
}
}
public int fibonacci(int n) {
if (n > 2) { // 从第二个数开始,就返回 (n-1) + (n-2) 的和。
return fibonacci(n - 1) + fibonacci(n - 2);
} else { // 如果没大于第二个,就是1。
return 1;
}
}
}