递归问题
1.分类
(1)打印问题(回顾递归调用机制)
(2)阶层问题
代码演示
class Demo{
public static void main(String[] args){
int res=test(4);
System.out.println("res="+res);
}
public static void test(int n){
if(n>2){
test(n-1);
}else{
System.out.println("n="+n);
}
}
}
递归调用机制的讲解
能解决的问题
1.各种数学问题,比如八皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题
2.各种算法中也会用到递归,比如,快排,归并排序,二分查找,分治算法
3.将栈解决的问题->递归代码比较简洁
迷宫问题
问题分析
迷宫可以用二维数组来表示,假设起点是map[1][1],终点是map[6][5],小球找路期间,行走方向的选择是 下->右->上->左,在此期间可以设定0表示通路没有走过,1表示通路走过,2表示通路可以走,3表示通路是死路
代码实现
package recursion;
public class Migong {
public static void mian(String[] args) {
//先创建一个二维数组,模拟迷宫
int[][] map=new int[8][7];
//使用1表示墙
//上下全部置为1
for(int i=0;i<7;i++) {
map[0][i]=1;
map[7][i]=1;
}
//左右全部置为1
for(int i=0;i<8;i++) {
map[i][0]=1;
map[i][6]=1;
}
//设置挡板1表示
map[3][2]=1;
map[3][2]=1;
//输出地图
System.out.println("地图的情况");
for(int i=0;i<8;i++) {
for(int j=0;j<7;j++) {
System.out.println(map[i][j]+" ");
}
System.out.println();//换行
}
//使用递归回溯,给小球找路
setWay(map,1,1);
//输出新的地图,小球走过,并标识过的地图
System.out.println("小球走过,并标识过的地图的情况");
for(int i=0;i<8;i++) {
for(int j=0;j<7;j++) {
System.out.println(map[i][j]+" ");
}
System.out.println();//换行
}
}
//使用递归回溯来给小球找路
//map表示地图
//i表示从哪个位置开始找,如果找到通路,就返回true,否则返回false
//如果小球能找到map[6][5]位置,则说明通路找到
//4.约定,当map[i][j]为0表示该点没有走过,当为1的时候表示走过,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;
}
}
}
}
八皇后问题(回溯算法的典型案例)
题目
在8*8的国际象棋上摆上8个皇后,使他们不能够互相攻击,即,任意两个皇后都不能处于同一行,同一列,或者同一斜线上,问有多少种摆法(下面是两种摆放的方法)
分析
与其用二维数组表示棋盘,由于八皇后互相不能在同一列,不如简化成一维数组的方式来表示摆放的方式,比如第一个棋盘的摆放方式就可以用数组arr[]={2,4,6,8,3,1,7,5}来表示,数组下标n用来表示第n+1个皇后,用arr[]来表示第n+1个皇后所在的行的位置
代码实现
首先写的是放置第n个皇后的judge方法,判断在该地方放置皇后是否正确。
要求:
1.不能在同一列,也就是一维数组各个元素不能相同
2.不能在同一斜线上,那么我们可以假设有两个皇后在一条斜线上,可以将它们连成一个等腰直角三角形,将第n个皇后和前面的所有放置过的皇后比较,那么就有条件Math.abs(n-i)==Math.abs(array[n]-array[i])也就是高和底相等。
接下来看代码 ss
package recursion;
public class Queue8 {
//定义一个max表示有多少个皇后
int max=8;
//定义数组array,保存皇后放置位置的结果,比如arr={0,4,7,5,2,6,1,3}
static int count=0;
int[] array=new int[max];
public static void main(String[] args) {
// TODO Auto-generated method stub
//测试一把,看8皇后是否正确
Queue8 queue8=new Queue8();
queue8.check(0);
System.out.printf("一共有%d种解法"+count);
}
//编写一个方法,放置第n个皇后
//特别注意,check是每一次递归的时候,进入到check种都有
private void check(int n) {
if(n==max) {
//n=8,
print();
}
//如果没有放完,依次判断是否冲突
for(int i=0;i<max;i++) {
//先把当前这个皇后,放到改行的第一列
array[n]=i;
//判断当放置第n个皇后到i列的时候是否冲突
if(judge(n)) {
//如果不冲突,接着放n+1个皇后,
check(n+1);
}
//一旦冲突,就回到上一个位置,就执行array[n]=i;即将第n个皇后放置在本行的后移的一个位置
}
}
//查看当我们放置第n个皇后,就去检测该皇后是否和前面已经摆放的皇后冲突
private boolean judge(int n) {
for(int i=0;i<n;i++) {
if(array[i]==array[n]||Math.abs(n-i)==Math.abs(array[n]-array[i])) {
return false;
}
}
return true;
}
//写一个方法,可以将皇后摆放的位置输出
private void print() {
count++;
for(int i=0;i<array.length;i++) {
System.out.print(array[i]+" ");
}
}
}
如果有不正确的地方希望能够指出,一起进步~~~~~~~~~