递归能够解决的问题:
1)数学问题:8皇后,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题
2)算法也会用到:快排,归并排序,二分查找,分治算法
3)将用栈解决的问题换成递归比较简洁
递归需要遵守的规则:
1)执行一个方法,就创建一个新的受保护的独立空间(栈空间)
2)方法的局部变量是独立的,不会相互影响,比如n变量
3)如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据
4)递归必须向退出递归的条件逼近,否则就是无限递归,
5)当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,
同时当方法执行完毕或者返回时,该方法也就执行完毕
迷宫问题:
1 public class MiGong { 2 public static void main(String[] args) { 3 //先创建一个二维数组,模拟迷宫 4 //地图 5 6 int[][] map = new int[8][7]; 7 //使用1 表示墙 8 //上下全部置为1 9 for (int i = 0; i < 7; i++) { 10 map[0][i]=1; 11 map[7][i]=1; 12 } 13 for (int i = 0;i<8; i++){ 14 map[i][0] =1 ; 15 map[i][6] =1; 16 } 17 //设置挡板,1表示 18 map[3][1] = 1; 19 map[3][2] = 1; 20 //map[1][2] = 1; 21 //map[2][2] = 1; 22 23 24 //输出地图 25 System.out.println("地图的情况"); 26 for (int i = 0; i < 8 ; i++) { 27 for (int j = 0; j < 7; j++) { 28 System.out.print(map[i][j]+" "); 29 } 30 System.out.println(); 31 } 32 //使用递归给小球找路 33 setWay2(map,1,1); 34 //输出新的地图,小球走过,并标识过的递归 35 System.out.println("小球走过,并标识过的地图"); 36 for (int i = 0; i < 8 ; i++) { 37 for (int j = 0; j < 7; j++) { 38 System.out.print(map[i][j]+" "); 39 } 40 System.out.println(); 41 } 42 43 } 44 // 45 46 //使用递归回溯来给小球找路 47 //说明: 48 //1.map 表示地图 49 //2.i,j 表示从地图的哪个位置开始出发(1,1) 50 //3. 如果小球能到map[6][5]位置,则说明通路找到 51 //4.约定:当map[i][j]为0时表示该点没有走过,当为1表示墙,为2表示通路可以走,为3表示该位置已经走过,但是走不通 52 //5.走迷宫时需要确定一个策略,先 下-右-上-左,如果该点走不通再回溯 53 /** 54 * 55 * 56 * @param map 57 * @param i 从哪个位置开始找 58 * @param j 59 * @return 如果找到通路,就返回true,否则返回false 60 */ 61 public static boolean setWay(int[][] map, int i,int j){ 62 int index =0; 63 if (map[6][5] == 2){ //通路已找到 64 return true; 65 }else{ 66 if (map[i][j] == 0){//如果当前这个点还没走过 67 //按照策略 68 map[i][j] =2 ;//假定该点可以走通 69 70 if (setWay(map,i+1,j)){//向下走 71 return true; 72 }else if (setWay(map,i,j+1)){//向右走 73 return true; 74 }else if(setWay(map,i-1,j)){//向上走 75 return true; 76 }else if (setWay(map,i,j-1)){//向左走 77 return true; 78 }else { 79 //说明该点走不通 80 map[i][j]=3; 81 return false; 82 } 83 }else { //如果map[i][j] != 0,可能是1,2,3 84 return false; 85 86 } 87 } 88 } 89 90 91 //修改找路策略,上右下左 92 public static boolean setWay2(int[][] map, int i,int j){ 93 if (map[6][5] == 2){ //通路已找到 94 return true; 95 }else{ 96 if (map[i][j] == 0){//如果当前这个点还没走过 97 //按照策略 98 map[i][j] =2 ;//假定该点可以走通 99 if (setWay2(map,i-1,j)){//向下走 100 return true; 101 }else if (setWay2(map,i,j+1)){//向右走 102 return true; 103 }else if(setWay2(map,i+1,j)){//向上走 104 return true; 105 }else if (setWay2(map,i,j-1)){//向左走 106 return true; 107 }else { 108 //说明该点走不通 109 map[i][j]=3; 110 return false; 111 } 112 }else { //如果map[i][j] != 0,可能是1,2,3 113 return false; 114 115 } 116 } 117 } 118 119 }
八皇后:
1 public class EightQueen { 2 3 //定义一个max表示共有多少个皇后 4 int max = 8; 5 //定义数组array,保存皇后放置位置的结果,比如arr={0,4,7,5,2,6,1,3} 6 int[] array = new int[max]; 7 static int count = 0; 8 public static void main(String[] args) { 9 EightQueen eightQueen = new EightQueen(); 10 eightQueen.check(0); 11 System.out.println(count); 12 } 13 //查看当我们放置第n个皇后时,去检测该皇后是否和前面已经放置的皇后冲突 14 15 16 //编写一个方法,放置第n个皇后 17 //注意;check是每一次递归时,进入到check中都有for循环 18 private void check(int n){ 19 if (n == max){//n=8 ,已经放好了 20 print(); 21 return; 22 } 23 //依次放入皇后,并判断是否冲突 24 for (int i = 0; i < max; i++) { 25 //先把当前皇后n,放到该行的第一列 26 array[n] = i; 27 //判断当放置第n个皇后到i列时,是否冲突 28 if (judge(n)){//不冲突 29 //接着放n+1个皇后,开始递归 30 check(n+1); 31 } 32 //如果冲突,就继续执行array[n] = i; 即将第n个皇后,放置在本行的后移的一个位置 33 } 34 } 35 36 /** 37 * 38 * @param n 表示第n个皇后 39 * @return 40 */ 41 private boolean judge(int n){ 42 for (int i = 0; i < n; i++) { 43 //说明 44 //1.array[i]==array[n] 表示判断第n个皇后是否和前面的n-1个皇后在同一列 45 //2. Math.abs(n-i)==Math.abs(array[n]-array[i] 表示判断第n个皇后是否和第i个皇后是否在同一斜线 46 //斜率为1 行差等于列差 47 //3.不需要判断判断是否在同一行,n每次都在递增 48 if (array[i] == array[n] || Math.abs(n-i)==Math.abs(array[n]-array[i])) { 49 50 return false; 51 } 52 } 53 return true; 54 } 55 56 //写一个方法,可以将皇后摆放位置打印出来 57 private void print(){ 58 count++; 59 for (int i = 0; i < array.length; i++) { 60 System.out.print(array[i] + " "); 61 } 62 System.out.println(); 63 } 64 }