3 递归
3.1 递归基础
- 递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
- 递归解决问题的思路:
- 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求
- 解递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
- 递归解决问题要找到两个内容:
- 递归出口:否则会出现内存溢出
- 递归规则:与原问题相似的规模较小的问题
public class Demo {
public static void main(String[] args) {
//回顾不死神兔:每个月兔子个数:1、1、2、3、5、8...;求第20月的兔子个数
int arr[] = new int[20];
arr[0] = 1;
arr[1] = 1;
for(int i=2;i< arr.length;i++) {
arr[i] = arr[i-1] + arr[i-2];
}
System.out.println(arr[19]); //6765
// f(20); //1,java.lang.StackOverflowError:当堆栈溢出发生时抛出一个应用程序递归抬深
System.out.println(f(20)); //6765
}
//递归解决问题首先定义个方法
public static int f(int n) {
//1,return f(n-1)+f(n-2);
//2,给出递归出口防止内存溢出
if(n==1 || n==2) {
return 1;
}else {
return f(n-1)+f(n-2);
}
}
}
3.2 案例1:递归求阶层
- 内存图解
public class Demo {
public static void main(String[] args) {
int number = jc(5);
System.out.println(number); //120
}
public static int jc(int n) {
if (n == 1) {
return 1;
} else {
return n * jc(n - 1);
}
}
}
3.3 案例2:遍历目录
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
//1:根据给定的路径创建一个File对象
File srcfile = new File("E:\\test");
// 6:调用方法
getAllFilePath(srcfile);
}
//2:定义一个方法,用于获取给定目录下的所有内容,参数为第1步创建的File对象
public static void getAllFilePath(File srcfile) {
//3:获取给定的File目录下所有的文件或者目录的File数组
File[] fileArray = srcfile.listFiles();
if(fileArray != null) {
//4:遍历该File数组,得到每一个File对象
for(File file:fileArray) {
//5:判断该File对象是否是目录
//public boolean isDirectory() 判断此抽象路径名表示的File是否为目录
if(file.isDirectory()) {
//是,递归调用,这此目录回到操作3
getAllFilePath(file);
}else {
//不是:获取绝对路径输出在控制台
//public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
System.out.println(file.getAbsoluteFile());
}
}
}
}
}
3.4 案例3:汉罗塔问题
汉诺塔问题描述:
- 有3根柱子A、B、C,A柱上有n个盘子,盘子的大小不等,大的盘子在下,小的盘子在上。
- 要求将A柱上的n个盘子移到C柱上,每次只能移动一个盘子。
- 在移动过程中,可以借助于任何一根柱子(A、B、C),但必须保证3根柱子上的盘子都是大的盘子在下,小的盘子在上。
思路:
- 可以理解成只有两种情况,当其中只有一个盘子,直接从A移动到C
- 当有两个的时候将第一个移动到B,最下面的移动到C,再将第一个移动到C
- 所以当有n个的时候,将上面的 n-1 当做一个整体移动到B,将 n 移动到C,再将上面的 n-1 移动到C
实现类
public class Hanoi {
public static void main(String[] args) {
hanoi(3,'A','B','C');
// 第1个盘子从A移动到C
// 第2个盘子从A移动到B
// 第1个盘子从C移动到B
// 第3个盘子从A移动到C
// 第1个盘子从B移动到A
// 第2个盘子从B移动到C
// 第1个盘子从A移动到C
}
//n:n个盘子,x:开始的柱子,y:中间的柱子,z:目标柱子
public static void hanoi(int n,char x,char y,char z) {
if(n==1) {
System.out.println("第1个盘子从"+x+"移动到"+z);
//无论有多少个盘子都认为只有两个。上面所有盘子为n-1,下面为n
}else {
//将前面n-1个盘子移到中间位置
hanoi(n-1,x,z,y);
//移动下面的盘子到目标位置
System.out.println("第"+n+"个盘子从"+x+"移动到"+z);
//把上面n-1个盘子从中间位置移动到目标位置
hanoi(n-1,y,x,z);
}
}
}