栈-3-递归能解决的问题总纲

递归调用的底层机制
递归调用
从jvm(虚拟机)入手, 方法栈的存在使得最后调用的方法, 最先执行.

递归能解决什么样的问题
1)求结果的数学问题
如: 8个皇后问题\ 汉诺塔问题\ 阶乘问题\ 迷宫问题\ 球和篮子问题
2)查找或者排序的算法问题
如: 快排\ 归并排序\ 二分查找\ 分治算法
3)将用栈解决的问题->递归代码比较简洁

递归的底层
1)执行一个方法时, 就创建一个新的受保护的独立空间(栈)
2)方法的局部变量是不会相互影响的
但是, 方法中使用的是引用类型的变量(如:数组)就会共享(这其实和变量在jvm中的位置有关)
3)递归必须向退出递归的条件逼近
4)当方法执行完毕或者遇到return时, 就会返回, 遵循谁调用就返回给谁, 方法也就结束.

递归解决迷宫问题(小球找路问题)
假设一个这样的迷宫(地图) 七行八列
1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1
1 1 1 0 0 0 0 1
1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1
出口就是map[5][6]的位置
入口就是map[1][1]的位置
思路: 约定0表示该点没有走过, 1表示墙, 2表示通路可以走, 3表示该点已经走过, 但是走不通
根据迷宫问题确定方向的优先级, 也就是走的策略
这里我们确定为 下>右>上>左

public class Migong {
    
    
    public static void main(String[] args) {
    
    
        int[][] map = new int[7][8];
        //设置围墙
        for (int i = 0; i < 7; i++){
    
    
            map[i][0] = 1;
            map[i][7] = 1;
        }
        for (int i = 0; i < 8; i++){
    
    
            map[0][i] = 1;
            map[6][i] = 1;
        }
        //设置挡板
        map[3][1] = 1;
        map[3][2] = 1;

        //查看初始地图
        for (int row = 0; row < map.length; row++){
    
    
            for (int col = 0; col < map[0].length; col++){
    
    
                System.out.print(map[row][col]+" ");
            }
            System.out.println();
        }

        if (canFindway(map, 1, 1)){
    
    
            System.out.println("能找到出口");
            for (int row = 0; row < map.length; row++){
    
    
                for (int col = 0; col < map[0].length; col++){
    
    
                    System.out.print(map[row][col]+" ");
                }
                System.out.println();
            }
        }else{
    
    
            System.out.println("没有出口");
        }
    }

    //判断能否找到路径
    public static boolean canFindway(int[][] map, int i, int j){
    
    
        //先判断是不是已经走到了终点
        if (map[5][6] == 2){
    
    
            return true;
        }else if(map[i][j] == 0){
    
    
            //说明该点能走
            map[i][j] = 2;
            if (canFindway(map, i+1, j)){
    
    
                return true;
            }else if (canFindway(map, i, j+1)){
    
    
                return true;
            }else if (canFindway(map, i-1, j)){
    
    
                return true;
            }else if (canFindway(map, i, j-1)){
    
    
                return true;
            }else{
    
    
                map[i][j] = 3;
                return false;
            }
        }else{
    
    
            return false;
        }
    }
}

解决八个皇后问题
回溯法: 也就是循环中配合递归
首先说明一下我们这里是使用一维数组来表示摆放的结果
索引表示第几个皇后, 也就是第几行, 值就是表示在第几列

public class Q8 {
    
    

    int max = 8; //确定有几个皇后
    int[] jieguo = new int[max]; //创建存放结果的容器
    static int count = 0; //创建结果种类计数器

    public static void main(String[] args) {
    
    
        Q8 q = new Q8();
        q.huisu(0); 
        System.out.printf("一共有%d种结果", count);
    }

    //创建一个回溯方法, 打印结果
    public void huisu(int n){
    
    
        if (n == max){
    
     //因为有max个皇后, 到max-1所有皇后都摆放上去了
            dayin();
            return;
        }
        for (int col = 0; col < max; col++){
    
    
            jieguo[n] = col; //每一个皇后, 也就是每一行, 所有的col都试一试
            if (!isChongtu(n)){
    
    
                huisu(n+1);
            }
        }
    }

    //创建一个判断当前皇后和之前放置的皇后是否有冲突的方法
    public boolean isChongtu(int n){
    
    
        for (int i = 0; i < n; i++){
    
     //如果是第一个皇后, 也就是n=0; 都不会进循环, 也就是都不用判断了
            if (jieguo[i] == jieguo[n] || Math.abs(n-i) == Math.abs(jieguo[n]-jieguo[i])){
    
    
                return true;
            }
        }
        return false;
    }


    //创建一个打印结果的方法
    public void dayin(){
    
    
        count++;
        for (int i = 0; i < jieguo.length; i++){
    
    
            System.out.print(jieguo[i]+" ");
        }
        System.out.println();
    }
}

Guess you like

Origin blog.csdn.net/weixin_45032905/article/details/121119084