参考资料
1. 概念
- 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
- 递归用到了虚拟机栈
2. 常见应用场景
-
八皇后问题
-
汉诺塔
-
求阶乘
-
迷宫问题
-
球和篮子
-
各种排序算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等.
3. 递归调用规则
-
方法的变量是独立的,不会相互影响的
-
如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据
-
递归必须向退出递归的条件逼近,否则就是无限递归,出现
StackOverflowError
-
当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或 者返回时,该方法也就执行完毕
4. 迷宫问题
4.1 思路
- 用一个二维矩阵map代表地图
0:代表未走过该地点
1:代表边界
2:代表走过且能走得通
3:代表走过但走不通 - 设置起点和终点以及每个地点的行走策略
行走策略指在该点所走的方向的顺序,如 下右上左(调用寻找路径的方法,使用递归) - 每次行走时假设该点能够走通,然后按照策略去判断,如果所有策略判断后都走不通,则该点走不通
4.2 对迷宫问题的讨论
- 小球得到的路径,和程序员设置的找路策略有关即:找路的上下左右的顺序相关
- 在得到小球路径时,可以先使用(下右上左),再改成(上右下左),看看路径是不是有变化,
- 测试回溯现象
- 思考:如何求出最短路径?
4.3 代码实现
代码实现参考gitee仓库。
5. 八皇后问题
5.1 问题介绍
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在 8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法(92)。
5.2 思路分析
-
将第一个皇后放在第一行第一列
-
将第二个皇后放在第二行第一列,判断是否会和其他皇后相互攻击,若会相互攻击,则将其放到第三列、第四列…直到不会相互攻击为止
-
将第三个皇后放在第三行第一列,判断是否会和其他皇后相互攻击,若会相互攻击,则将其放到第三列、第四列…直到不会相互攻击为止,并以此类推,在摆放的过程中,有可能会改动前面所放的皇后的位置
-
直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解。
-
当得到一个正确的解时,就会回溯到上一行,由此来找出第一个皇后在第一行第一列的所有解
-
再将第一个皇后放到第一行第二列,并重复以上步骤
- 棋盘本身应该是用二维数组表示,但是因为皇后所在的行数是固定的,所以可以简化为用一个一维数组来表示。其中的值代表皇后所在的列 数组下标代表皇后所在行数,即
arr[i] =val;
val
表示第i+1
个皇后,放在第i+1
行的第val+1
列- 所以判断是否在同一行列斜线上时,只需要判断是否在同一列和同一斜线上即可
- 是否同列判断:值是否相同
- 是否同一斜线:
行号-行号
是否等于列号-列号
,且列号相减要取绝对值