Java SE 递归
一、递归的概念
一个方法在执行过程中调用自身,就称为"递归"(也称自己调用自己)
递归的必要条件:
- 递归出口(即结束递归的条件)
- 将原问题划分称成其子问题,且子问题必须要与原问题的解法相同
代码示例: 递归求n的阶乘
public class Test {
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
if (n == 1) { //n等于1为递归出口
return 1;
}
return n * factor(n - 1); //这里再次调用了factor()这个方法
}
}
//执行结果
ret = 120
二 、递归执行过程分析
递归的程序的执行过程不太容易理解,要想理解清楚递归,必须先理解清楚”方法的执行过程“,尤其是”方法执行结束之后,回到调用位置继续往下执行“.
这里用代码来展示会更加便于理解
代码示例: 递归求n的阶层:
public class Test {
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
System.out.println("函数开始,n = " + n);
if (n == 1) {
System.out.println("函数结束,n = 1 ret = 1");
return 1;
}
int ret = n * factor(n - 1);
System.out.println("函数结束, n = " + n + " ret = " + ret);
return ret;
}
}
//执行结果
函数开始,n = 5
函数开始,n = 4
函数开始,n = 3
函数开始,n = 2
函数开始,n = 1
函数结束,n = 1 ret = 1
函数结束,n = 2 ret = 2
函数结束,n = 3 ret = 6
函数结束,n = 4 ret = 24
函数结束,n = 5 ret = 120
ret = 120
执行过程图
程序按照序号中标识的(1) --> (8) 的顺序执行,在方法执行过程中调用自身,并在达到递归结束条件后返回,回到调用位置继续往下执行
三、递归练习
通过代码实现斐波那契数列,求出斐波那契数列第N项
代码示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(fib(n));
}
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
}
补充:
当我们求fib(40)的时候发现,程序执行速度极慢,原因是进行了大量的重复运算,这里可以进行一段代码测试
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(fib(n));
System.out.println(count);
}
public static int count = 0;
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
if (n == 3) {
count++;
}
return fib(n - 1) + fib(n - 2);
}
}
//执行结果
102334155
39088169 //fib(3)重复执行了三千万次
可见用递归实现斐波那契数列在获取较大数字时效率较低,可以使用循环的方法来解决斐波那契数列问题,避免出现冗余运算
代码示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(fib1(n));
}
public static int fib1(int n) {
int last1 = 1, last2 = 1, tmp = 0;
if (n == 1 || n == 2) {
return 1;
}
for (int i = 3;i <= n;i++) {
tmp = last1;
last1 = last2;
last2 = tmp + last1;//此时的last1为开始的last2,tmp存放着开始的last1
}
return last2;
}
}
修改后的程序执行效率大大提高!!