一、递归的概念与回顾
1.递归
递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
2.回顾
(1)阶乘计算
思路分析: 写一个方法,传入一个n值,计算n值的阶乘 递归需要一个末值,也就是执行最后的值,在阶乘中为1 如果此时n不为1,就返回n乘factorical(--n)
public int factorial(int n){
if(n == 0){
return 0;
}
if(n == 1){
return 1;
}else {//这里factorial(--n),如果传入的是n--,那么根据传参规则,就会把n传递进去,就会形成死循环
return n * factorial(--n);
}
}
(2)打印问题
public void test(int i){
if(i > 2){
test(i - 1);
}
System.out.println("i = "+i);
}
询问输出什么?
根据递归的性质可以看出,如果i>2,那就会一直调用test方法,直到i==2,那么i==2就是该递归的末值,所以输出为i = 2 ====>(一直到) i = i;
二、迷宫问题
1.迷宫路径查找
思路分析: 1.传入迷宫地图的数组,迷宫上小球的初始位置数组,迷宫终点位置数组 2.如果当前小球位置等于终点位置,那么说明已走完 3.如果当前小球位置不等于终点位置,那么就让他行走 4.根据终点位置与当前位置的关系,设置行走的优先级顺序: 5.如果终点的x值大于当前x值,那就向下走,如果终点y值大于当前y值,那就向右走 6.用2代表走过的路,1代表墙,0代表可以走的路 7.拓展:(1)如果走入了死胡同内,那么就原路返回一个值,并将死胡同的地方设置为3 (2)返回一位后,判断其他位置,如果还是死胡同,继续返回,反复
public void findWay(int[][] maps, int[] start, int[] end) {
//结束条件
if (start[0] == end[0] && start[1] == end[1]) {
return;
} else {//优先上下,其次左右
if (start[0] > end[0]) {//当前x值大于终点x值,那向上移动
if (maps[start[0] - 1][start[1]] == 0) {
start[0] = start[0] - 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
} else if (maps[start[0] - 1][start[1]] == 1 || maps[start[0] - 1][start[1]] == 3) {
if (start[1] > end[1]) {
if (maps[start[0]][start[1] - 1] == 0) {
start[1] = start[1] - 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
} else if (maps[start[0]][start[1] - 1] == 1 || maps[start[0]][start[1] - 1] == 3) {
maps[start[0]][start[1]] = 3;
start[1] = start[1] + 1;
findWay(maps, start, end);
}
} else if (start[1] <= end[1]) {
if (maps[start[0]][start[1] + 1] == 0) {
start[1] = start[1] + 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
} else if (maps[start[0]][start[1] + 1] == 1 || maps[start[0]][start[1] + 1] == 3) {
maps[start[0]][start[1]] = 3;
start[1] = start[1] - 1;
findWay(maps, start, end);
}
}
}
} else if (start[0] <= end[0]) {
if (maps[start[0] + 1][start[1]] == 0) {
start[0] = start[0] + 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
} else if (maps[start[0] + 1][start[1]] == 1) {
if (start[1] > end[1]) {
if (maps[start[0]][start[1] - 1] == 0) {
start[1] = start[1] - 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
}
} else if (start[1] <= end[1]) {
if (maps[start[0]][start[1] + 1] == 0) {
start[1] = start[1] + 1;
maps[start[0]][start[1]] = 2;
findWay(maps, start, end);
}
}
}
}
//移动的
}
}
使用我的方法会显得代码非常复杂,又臭又长,所以根据老师讲述,进行修改后
2.精简版迷宫寻路
思路分析:传入地图的二维数组,当前x,y坐标以及最后的终点位置 1.设置墙为1,可以走的路为0,走过的路为2,如果地图上的终点位置为2,那么表示走完 2.走路优先级:下右上左 3.每次判断能不能走,能走返回true 4.如果此时走进死胡同,那便回溯,将当前值置为3,返回false,重新找路
public static boolean findWay2(int[][] maps,int x,int y,int[] end){
if(maps[end[0]][end[1]] == 2){
return true;
}else {
if(maps[x][y] == 0) {
maps[x][y] = 2;
if (findWay2(maps, x + 1, y, end)) {
return true;
} else if (findWay2(maps, x, y + 1, end)) {
return true;
} else if (findWay2(maps, x - 1, y, end)) {
return true;
} else if (findWay2(maps, x, y - 1, end)) {
return true;
} else {
maps[x][y] = 3;
return false;
}
}else {
return false;
}
}
}
三、八皇后
思路分析: 1.实现八皇后问题,就是在八乘八的棋盘上,每一行放一个皇后,皇后不能重行,不能重列,不能重斜线 2.使用一维数组实现,数组中的每个元素都不能相同,且每两个元素直接不能相连,即不能1,2这样 3.需要一个计数属性,用于计算实现的八皇后排序次数
public class EightQueen {
public static void main(String[] args) {
new EightQueen().check(0);
System.out.println(count);
}
//创建输出结果集
private int[] result = new int[8];
private static int judgeCount = 0;
private static int count = 0;
//写出遍历方法
public void list(){
System.out.print("[\t");
for (int i:result) {
System.out.print(i + "\t");
}
System.out.print("]");
System.out.println();
count++;
}
//八皇后问题
/*
思路分析:
1.实现八皇后问题,就是在八乘八的棋盘上,每一行放一个皇后,皇后不能重行,不能重列,不能重斜线
2.使用一维数组实现,数组中的每个元素都不能相同,且每两个元素直接不能相连,即不能1,2这样
3.需要一个计数属性,用于计算实现的八皇后排序次数
*/
//编写一个方法,放置第n个皇后
//特别注意: check 是 每一次递归时,进入到check中都有 for(int i = 0; i < max; i++),因此会有回溯
private void check(int n) {
if(n == result.length) { //n = 8 , 其实8个皇后就既然放好
list();
return;
}
//依次放入皇后,并判断是否冲突
for(int i = 0; i < result.length; i++) {
//先把当前这个皇后 n , 放到该行的第1列
result[n] = i;
//判断当放置第n个皇后到i列时,是否冲突
if(judge(n)) { // 不冲突
//接着放n+1个皇后,即开始递归
check(n+1); //
}
//如果冲突,就继续执行 array[n] = i; 即将第n个皇后,放置在本行得 后移的一个位置
}
}
//查看当我们放置第n个皇后, 就去检测该皇后是否和前面已经摆放的皇后冲突
/**
*
* @param n 表示第n个皇后
* @return
*/
private boolean judge(int n) {
judgeCount++;
for(int i = 0; i < n; i++) {
// 说明
//1. array[i] == array[n] 表示判断 第n个皇后是否和前面的n-1个皇后在同一列
//2. Math.abs(n-i) == Math.abs(array[n] - array[i]) 表示判断第n个皇后是否和第i皇后是否在同一斜线
// n = 1 放置第 2列 1 n = 1 array[1] = 1
// Math.abs(1-0) == 1 Math.abs(array[n] - array[i]) = Math.abs(1-0) = 1
//3. 判断是否在同一行, 没有必要,n 每次都在递增
if(result[i] == result[n] || Math.abs(n-i) == Math.abs(result[n] - result[i]) ) {
return false;
}
}
return true;
}
}