递归和回溯
递归需要遵守的重要规则
- 执行一个方法时,就创建一个新的受保护的独立空间 (栈空间)
- 方法的局部变量是独立的,不会相互影响,比如 n 变量
- 如果方法中使用的是引用类型变量 (比如数组),就会共享该引用类型的数据.
- 递归必须向退出递归的条件逼近,否则就是无限递归,死龟了 😃
- 当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
递归用于解决什么样的问题
- 各种数学问题如:8 皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题 (google 编程大赛)
- 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等.
- 将用栈解决的问题 --> 递归代码比较简洁
迷宫问题
public class MazeSolver {
private static final int PATH = 2; // 路径标记
private static final int WALL = 1; // 墙
private static final int VISITED = 3; // 已访问标记
public static void main(String[] args) {
int[][] maze = {
{1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1}
};
System.out.println("迷宫地图:");
printMaze(maze);
if (findPath(maze, 1, 1)) {
System.out.println("\n找到路径:");
printMaze(maze);
} else {
System.out.println("\n没有找到路径!");
}
}
// 递归回溯法找路径
public static boolean findPath(int[][] maze, int row, int col) {
int rows = maze.length;
int cols = maze[0].length;
// 判断是否是出口(右下角)
if (row == rows - 2 && col == cols - 2) {
maze[row][col] = PATH;
return true;
}
// 判断当前位置是否可走
if (isValid(maze, row, col)) {
maze[row][col] = PATH; // 标记为路径
// 下右上左的顺序尝试
if (findPath(maze, row + 1, col)) return true;
if (findPath(maze, row, col + 1)) return true;
if (findPath(maze, row - 1, col)) return true;
if (findPath(maze, row, col - 1)) return true;
// 如果四个方向都走不通,回溯
maze[row][col] = VISITED;
return false;
}
return false;
}
// 检查位置是否有效
public static boolean isValid(int[][] maze, int row, int col) {
return row >= 0 && row < maze.length &&
col >= 0 && col < maze[0].length &&
maze[row][col] == 0; // 0表示可走
}
// 打印迷宫
public static void printMaze(int[][] maze) {
for (int[] row : maze) {
for (int cell : row) {
switch (cell) {
case 0: System.out.print(" "); break; // 通路
case 1: System.out.print("█ "); break; // 墙
case 2: System.out.print("* "); break; // 路径
case 3: System.out.print("× "); break; // 已访问
}
}
System.out.println();
}
}
}