用递归解决迷宫问题完整代码在最下方,不想看前面啰嗦的,请直接划到最下方。
6.1 递归应用场景
看个实际应用场景,迷宫问题(回溯), 递归(Recursion)
6.2 递归的概念
简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时
可以让代码变得简洁。
6.3 递归调用机制
我列举两个小案例,来帮助大家理解递归。
- 打印问题
- 阶乘问题
- 使用图解方式说明了递归的调用机制
4. 代码演示
/**
* @author zk
* @version 1.0.0
* @ClassName Test.java
* @Description TODO 递归demo
* @createTime 2021年10月08日 10:39:00
*/
public class RecursionTest {
public static void main(String[] args) {
//通过打印问题,回顾递归调用机制
//test(4);
int res = factorial(3);
System.out.println("res=" + res);
}
//打印问题.
public static void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n=" + n);
}
//阶乘问题
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return factorial(n - 1) * n; // 1 * 2 * 3
}
}
}
6.4 递归能解决什么样的问题
- 各种数学问题如: 8 皇后问题 , 汉诺塔, 阶乘问题, 迷宫问题, 球和篮子的问题(google 编程大赛)
- 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等.
- 将用栈解决的问题–>递归代码比较简洁
6.5 递归需要遵守的重要规则
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)。
- 方法的局部变量是独立的,不会相互影响, 比如 n 变量。
- 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据。
- 递归必须向退出递归的条件逼近,否则就是无限递归,出现 StackOverflowError,死归了)。
- 当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
6.6 递归-迷宫问题
6.6.1 代码实现
/**
* @author zk
* @version 1.0.0
* @ClassName MiGong.java
* @Description TODO 递归解决迷宫问题
* @createTime 2021年09月23日 10:05:00
*/
public class MiGong {
public static void main(String[] args) {
int[][] map = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 1; i <= 6; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
map[2][2] = 1;
// ↑上面是制作地图
// 显示地图
for (int[] row : map) {
for (int col : row) {
System.out.print(col + "\t");
}
System.out.println();
}
System.out.println("-------------------------");
// 走迷宫
setWay(map,1,1);
// 显示路线
for (int[] row : map) {
for (int col : row) {
System.out.print(col + "\t");
}
System.out.println();
}
}
//使用递归回溯来给小球找路
//说明
//1. map 表示地图
//2. i,j 表示从地图的哪个位置开始出发 (1,1)
//3. 如果小球能到 map[6][5] 位置,则说明通路找到.
//4. 约定: 当 map[i][j] 为 0 表示该点没有走过 当为 1 表示墙 2 表示通路可以走 ; 3 表示该点已经走过,但是走不通
//5. 在走迷宫时,需要确定一个策略(方法) 下->右->上->左 , 如果该点走不通,再回溯
public static boolean setWay(int[][] map,int i,int j){
if (map[6][5]==2){
//表示路线已经找到
return true;
}else {
if (map[i][j]==0){ //说明该点没走过
map[i][j] = 2;
if (setWay(map,i+1,j)){ //往下走
return true;
}else if (setWay(map,i,j+1)){ //往右走
return true;
}else if (setWay(map,i-1,j)){ //往上走
return true;
}else if (setWay(map,i,j-1)){ //往左走
return true;
}else { //都走不通
map[i][j] = 3;
return false;
}
}else {
// 该点不是0 就是 1 或 2 或3 均不可在走 所以直接返回false
return false;
}
}
}
// 如果想要求最短路径,改变下->右->上->左这个策略,把所有策略都走一遍,看看哪个路线最短
}