递归

 

正文

一、简介

1,概念

  递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

2,调用机制

       

3,递归需遵循的规则

  • 执行一个方法时, 就创建一个新的受保护的独立空间(栈空间)
  • 方法的局部变量是独立的, 不会相互影响, 比如 n 变量
  • 如果方法中使用的是引用类型变量(比如数组), 就会共享该引用类型的数据
  • 递归必须向退出递归的条件逼近, 否则就是无限递归,出现 StackOverflowError, 死龟了 😃
  • 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。

二、迷宫问题

              

  源码: 迷宫源码

1,思路

1)使用二维数组 map[][] 模拟迷宫
2)约定: 当 map[i][j] 为 0 表示该点没有走过;当为 1 表示墙;2 表示通路可以走 ;3 表示该点已经走过,但是走不通
3)getWay() 方法用于找路,true 表示该路可以走通,false 表示该路走不通
4)在走迷宫时,需要确定一个策略(方法) 下->右->上-> , 一步一步向前试探,如果该点走不通,再回溯
5)每当走到一个点时,将该点置为 2 ,暂时假设该路能走通,至于到底走不走得通,得看后面有没有找到通路
    如果后面的路能走通,从最后一个点开始返回,整个 getWay() 递归调用链都返回 true
    如果后面的路不能走通,那么将当前的点设置为 3 ,表示是死路,走不通,回溯至上一个点,看看其他方向能不能走通

2,代码实现

复制代码
public static void main(String[] args) {
    int[][] arr = init(8, 7);
    arr[3][1] = 1;
    arr[3][2] = 1;
    arr[1][2] = 1;
    arr[2][2] = 1;
    show(arr);
//        getWay(arr, 1, 1);
    getWay1(arr, 1, 1);
    System.out.println("==============================");
    show(arr);
}

//右下左上
public static boolean getWay1(int[][] arr, int i, int j) {
    if (arr[6][5] == 2) {
        return true;
    } else {
        if (arr[i][j] == 0) { //这条路还没有走过
            //设置这条路为可以走
            arr[i][j] = 2;
            if (getWay1(arr, i, j + 1)) { //右边这条路是通路
                return true;
            } else if (getWay1(arr, i + 1, j)) { //下面这条路是通路
                return true;
            } else if (getWay1(arr, i, j - 1)) { //左边这条路是通路
                return true;
            } else if (getWay1(arr, i - 1, j)) { //上这条路是通路
                return true;
            } else {
                arr[i][j] = 3;
                return false;//否则就是没有通路
            }
        } else { //如果(arr[i][j]为 1 , 3 则返回false此路不通
            return false;
        }
    }
}

//下右上左
//约定: 当 map[i][j] 为 0 表示该点没有走过 当为 1 表示墙 ; 2 表示通路可以走 ; 3 表示该点已经 走过,但是走不通
public static boolean getWay(int[][] arr, int i, int j) {
    if (arr[6][5] == 2) {
        return true;
    } else {
        if (arr[i][j] == 0) { //这条路没走过
            //假设这条路可以走通
            arr[i][j] = 2;
            if (getWay(arr, i + 1, j)) {//
                return true;
            } else if (getWay(arr, i, j + 1)) {//
                return true;
            } else if (getWay(arr, i - 1, j)) {//
                return true;
            } else if (getWay(arr, i, j - 1)) {//
                return true;
            } else {
                arr[i][j] = 3;
                return false;
            }
        } else { //如果 map[i][j] != 0 , 可能是 1, 3
            return false;
        }
    }

}

/**
 * 遍历数组
 */
private static void show(int[][] arr) {
    for (int[] ints : arr) {
        for (int anInt : ints) {
            System.out.printf("%d\t", anInt);
        }
        System.out.println();
    }
}

/**
 * 初始化数组
 *
 * @param h 高
 * @param w 宽
 */
private static int[][] init(int h, int w) {
    int[][] arr = new int[h][w];
    for (int i = 0; i < w; i++) {
        arr[0][i] = 1;
        arr[h - 1][i] = 1;
    }
    for (int i = 0; i < h; i++) {
        arr[i][0] = 1;
        arr[i][w - 1] = 1;
    }
    return arr;
}
View Code
复制代码

三、八皇后问题(回溯算法)

        

  源码:八皇后问题源码

1,思路

1)第一个皇后先放在第一行第一列
2)第二个皇后放在第二行第一列,然后判断是否符合条件[是否冲突],如果不符合,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
3)继续第三个皇后,还是第一列、第二列...直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
4)当得到一个正确解,在栈中回退到上一个栈时,就会开始回溯,即将第一个皇后,放在第一列的所有正确解,全部得到
5)然后回头继续第一个皇后放第二列,后面继续循环执行1,23,4的步骤

2,代码实现

复制代码
/**
 * 放置第n个皇后
 *
 * @param n
 */
private void check(int n) {
    //如果排序到最大值  就退出循环
    if (n >= max) {
        count++;
        System.out.println(Arrays.toString(arr));
        return;
    }
    for (int i = 0; i < max; i++) {
        //先设置第n个皇后的值为i
        arr[n] = i;
        //判断当前皇后值是否符合,如果符合就进行下一个
        if (judge(n)) {
            check(n + 1);
        }
    }
}

private boolean judge(int n) {
    judgeNum++;
    for (int i = 0; i < n; i++) {
        int index = Math.abs(n - i);
        int val = Math.abs(arr[n] - arr[i]);
        if (index == val || n == i || arr[n] == arr[i]) {
            return false;
        }
    }
    return true;
}
View Code
复制代码

 

posted @   MXC肖某某  阅读(122)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示