1、简单的递归算法
1、打印问题代码实现
public class RecursionTest {
public static void main(String[] args) {
test(4);
}
private static void test(int n){
if(n>2){
test(n-1);
}
System.out.println("n="+n);
}
}
1、递归调用机制:向下传递,向上回归
通过直接或间接地调用自身的形式的一种算法
JVM中递归调用原理
2、递归过程中的规律
1、当程序执行一个方法时就会开辟一个独立的空间【栈】
2、每个空间的数据是独立的
2、阶乘问题代码实现
private static int multi(int n){
if (n==1){
return 1;
}else {
return multi(n-1)*n;
}
}
2、递归解决的实际问题
1、迷宫问题
/**
* @author zhihua.li
* @date 2021/2/1 - 8:06
* 递归法解决迷宫问题
**/
public class MiGong {
public static void main(String[] args) {
// 初始化迷宫,0表示道路,1表示墙壁
int[][] map = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
setWay(map, 1, 1);
System.out.println("通过迷宫后:");
int count = 0;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
if (map[i][j] == 2) {
count++;
}
System.out.print(map[i][j] + " ");
}
System.out.println();
}
System.out.println("从迷宫起点到终点共走过了" + count + "个点!");
}
/**
* @param map 迷宫
* @param i 起始位置的行
* @param j 起始位置的列
* @Method setWay
* @Author zhihua.Li
* @Version 1.0
* @Description 1、map表示地图
* 2、i,j共同决定出发时的起始位置
* 3、若小球能到[6][5]位置,说明通路找到
* 4、map[i][j] 为0表示没走过该点;1为墙;2为可以走;3为已走却走不通
* 5、走迷宫前需要定下策略:下->右->上->左,走不通再回归
* @Return boolean 找到通路返回true,否则false
* @Exception
* @Date 2021/2/1 8:26
*/
private static boolean setWay(int[][] map, int i, int j) {
int count = 0;
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 {
/*map[i][j]!=0,为1,2,3*/
return false;
}
}
}
}
运行结果:
2、八皇后问题
/**
* @author zhihua.li
* @date 2021/2/1 - 9:59
**/
public class EightQueen {
int max = 8;
int array[] = new int[max]; //接收max个皇后的位置
static int count = 0; //接收共有多少种不同的摆放方法
static int judgeCount = 0; //接收共需要判断多少次
public static void main(String[] args) {
EightQueen eightQueen = new EightQueen();
eightQueen.check(0);
System.out.println("共有" + count + "种摆放顺序");
System.out.println("共检查了" + judgeCount + "个摆放位置");
}
/**
* @param n
* @Method check
* @Author zhihua.Li
* @Version 1.0
* @Description 判断并放置皇后
* 每一个位置都有for循环,所以自带回溯效果,也就是会取到所有的情况而不只是一种
* @Return void
* @Exception
* @Date 2021/2/1 11:14
*/
private void check(int n) {
if (n == max) { //8皇后问题,max为8,当n==8时,也就说明0-7共8个皇后已经放好
print();
return;
}
for (int i = 0; i < max; i++) {
/*这里的i表示的其实是棋盘的列数,而题目中为8皇后,也就是说每一行都有8个位置,所以i最大为max*/
/*把第n个皇后放在第i个位置上*/
array[n] = i;
/*判断是否冲突,如果不冲突就开始放下一个皇后,否则就把当前皇后放到当前列的下一个位置上(for循环)*/
if (judge(n)) {
check(n + 1);
}
}
}
/**
* @param n 表示第n个皇后
* @Method judge
* @Author zhihua.Li
* @Version 1.0
* @Description
* @Return boolean 返回结果为true说明第n个皇后有放处,即前n-1个皇后不冲突
* @Exception
* @Date 2021/2/1 10:51
*/
private boolean judge(int n) {
judgeCount++;
for (int i = 0; i < n; i++) {
/*
* array[n] == array[i]判断是否在同一列
* (n-i)==Math.abs(array[n]-array[i])判断是否有两个皇后在同一个对角线上
* 不需要判断是否在同一行,因为i是递增的,是不断变化的
*
* */
if (array[n] == array[i] || (n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
/**
* @param
* @Method print
* @Author zhihua.Li
* @Version 1.0
* @Description 用来打印n皇后的摆放序列
* @Return void
* @Exception
* @Date 2021/2/1 10:53
*/
private void print() {
count++;
for (int i = 0; i < max; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
运行结果: