递归
递归的基本概念
简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
递归调用机制图解
递归需要遵守的重要原则
执行一个方法时,就创建一个新的受保护的独立空间(栈空间)。
方法的局部变量是独立的,不会相互影响,比如n变量。
如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据。
递归必须向退出递归的条件逼近,否则就是无限递归,出现(StackOverflowError,栈溢出错误)
当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
迷宫问题
问题描述
找出一条从入口到出口的路
回溯法实现
package com.athome.recursion;
/**
* Description:
* Author:江洋大盗
* Date:2021/1/22 18:48
*/
public class Maze {
public static void main(String[] args) {
int[][] map = new int[8][7];
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 5; i++) {
map[3][i] = 1;
}
for (int i = 5; i > 1; i--) {
map[5][i] = 1;
}
findWay(map, 1, 1);
//输出map
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + "t");
}
System.out.println();
}
}
/**
* 探索思路:下-右-上-左
* 0:表示没有探索过的地方
* 1:表示墙
* 2:表示可以走通的路
* 3:表示走不通的路
*
* @param map 表示迷宫的数组
* @param i 起始坐标
* @param j 起始坐标
* @return 返回是否找到正确的路
*/
public static boolean findWay(int[][] map, int i, int j) {
//代表正确找到了终点,递归结束
if (map[6][5] == 2) {
return true;
} else {
//表示还没有探索过的地方
if (map[i][j] == 0) {
//先假设可以走通
map[i][j] = 2;
if (findWay(map, i + 1, j)) {
return true;
} else if (findWay(map, i, j + 1)) {
return true;
} else if (findWay(map, i - 1, j)) {
return true;
} else if (findWay(map, i, j - 1)) {
return true;
} else {
map[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
}
八皇后问题
问题介绍
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。
代码实现
package com.atschool.recursion;
/**
* Description:
* Author:江洋大盗
* Date:2021/1/22 19:15
*/
public class Queen8 {
static int maxSize = 8;//表示棋盘的大小
static int[] solution = new int[maxSize];//存放每一种解法
static int count = 0;//记录有多少种解法
static int judgeNum = 0;//记录一共判断多少次
/**
* 输出方法
*/
public static void print() {
count++;
for (int i : solution) {
System.out.print(i + "t");
}
System.out.println();
}
/**
* 判断当前位置是否可以落棋
*
* @param n 表示当前棋子位置
* @return 若当前位置可行,返回true,否则返回false
*/
public static boolean judge(int n) {
judgeNum++;
for (int i = 0; i < n; i++) {
if (solution[i] == solution[n] ||
Math.abs(n - i) == Math.abs(solution[n] - solution[i])) {
return false;
}
}
return true;
}
/**
* @param n 第n个皇后
*/
public static void check(int n) {
//限定结束条件
if (n == maxSize) {
print();
return;
}
for (int i = 0; i < maxSize; i++) {
//先把当前皇后n,放到该行的第i列
solution[n] = i;
//判断该位置是否可行
if (judge(n)) {
//如果可行就放下一个皇后
check(n + 1);
}
//如果冲突就继续放置该皇后,放置位置后移一个
}
}
public static void main(String[] args) {
check(0);
System.out.println("共有" + count + "种解法.");
System.out.println("共判断了" + judgeNum + "次.");
}
}
结语
只要能收获甜蜜,荆棘丛中也有蜜蜂忙碌的身影,未来的你一定会感谢现在努力的自己。