递归思想

递归

简单来讲就是自己调用自己,每次传入不同的变量,递归有助于编程者解决复杂的问题,同时让代码
变得比较简洁
递归可以使用在很多地方,比如快速排序,归并排序等等

打印输出问题

	public static void test(int n){
    	if (n>2){
        	test(n-1);
    	}
    	System.out.println("n="+n);
	}

阶乘问题

	public static int test2(int n){
        if (n==1){
            return n;
        }else {
            return n*test2(n-1);
        }
    }

递归需要遵守的重要规则

1.执行一个方法时,就会产生一个独立的空间(栈空间)
2.方法的局部变量是独立的,不会相互影响,不如n变量
(如果方法中使用的是引用类型的变量,就会共享该引用类型的数据比如数组)
3.递归必须向递归的条件逼近,否则就是死递归,发生栈溢出
5.当一个方法执行完毕后,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当
方法执行完毕或者返回是,该方法就执行完毕

迷宫问题

//使用递归回溯给小球找路
    //1.i,j是从那个位置开始找
    //2.如果找到通路就返回true,找不到就返回false
    //3.如果小球能到map[6][5],说明通路找到
    //4.当map[i][j]为0时,表示该点还没有走过,当为2时候表示是通路还没有走,3表示该点已经
	走过,但是走不通
    //5.我们在走迷宫时候必须有一个策略,比如 下-》右-》上-》左

代码实现

	public static boolean setWay(int[][] map,int i,int j){
        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最少的地图就是最短路径

八皇后问题

在8*8格的国际象棋上摆放八个皇后,是其不能互相攻击,即:任意两个皇后都不能处于同一行,同
一列或同一斜线上,问有多少种摆法

思路分析
1.将第一个皇后放在第一行第一列
2.将第二个皇后放在第二行第一列。然后判断是否ok,如果不ok就继续放在第二列,第三列,一次将
所有的列都放完,找到一个合适的
3.继续将第三个皇后还是像第二行的皇后一样
4.当的到一个正确的解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放在第一列所
有的正确解,全部都得到
5.然后回头继续将第一个皇后放第二列,后面继续循环1,2,3,4的步骤

说明:理论上应该创建一个二位数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解
决问题,arr[8]={0,4,7,5,2,6,1,3}下标对应的是行,元素对应的是列;arr[i]=val,表示第i+1
行,第val+1列

代码实现

public class Queue8 {
    //定义一个max表示共有多少个皇后
    static int max=8;
    //定义一个数组,保存皇后放置位置的结果,比如 arr[8]={0,4,7,5,2,6,1,3}
    static int[] array=new int[8];
    static int count=0;
    public static void main(String[] args) {
        check(0);
        System.out.println("一共有"+count+"种解法");
    }

    //编写一个方法放置第n个皇后
    private static void check(int n){
        if (n==max){//n==8 ,其实八个皇后已经放好了
            count++;
            print();
            return;
        }
        //依次放入皇后,并判断是否冲突
        for (int i=0;i<max;i++){
            //先把当前这个皇后n放到该行的第一列
            array[n]=i;
            //判断当第n个皇后放i列时,是否冲突
            if (judge(n)){//说明不冲突
                //接着放第n+1个皇后,开始递归
                check(n+1);
            }
            //如果冲突就继续执行array[n]=i;即将第n个皇后防止在本行的后移的一个位置
        }

    }

    //查看当我们放置第n个皇后,就去检测该皇后是否和前面已经摆放的皇后冲突
    //n表示第n个皇后
    private static boolean judge(int n){
        for (int i=0;i<n;i++){
            //1.array[i]==array[n] 表示判断第n个皇后是否和第i个皇后在同一列
            /*2.Math.abs(n-i)== Math.abs(array[n]-array[i] 表示判断第n个皇后是否和第i个
		皇后在同一斜线,可以放在坐标系中理解*/
            //3.判断是否在同一行,没有必要判断,因为n每一次都在递增,所以不可能在同一行
            if (array[i]==array[n] || Math.abs(n-i)== Math.abs(array[n]-array[i])){
                return false;
            }
        }
        return true;
    }

    //写一个方法,可以将皇后摆放的位置打印出来
    private static void print(){
        for (int value : array) {

            System.out.print(value + " ");
        }
        System.out.println();
    }
}
posted @ 2021-10-05 23:46  Jack+_+  阅读(202)  评论(0)    收藏  举报