递归
正文
一、简介
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; }
三、八皇后问题(回溯算法)
源码:八皇后问题源码
1,思路
1)第一个皇后先放在第一行第一列 2)第二个皇后放在第二行第一列,然后判断是否符合条件[是否冲突],如果不符合,继续放在第二列、第三列、依次把所有列都放完,找到一个合适 3)继续第三个皇后,还是第一列、第二列...直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解 4)当得到一个正确解,在栈中回退到上一个栈时,就会开始回溯,即将第一个皇后,放在第一列的所有正确解,全部得到 5)然后回头继续第一个皇后放第二列,后面继续循环执行1,2,3,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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话