递归问题笔记总结

递归问题

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.将栈解决的问题->递归代码比较简洁

迷宫问题

迷宫回溯问题--java实现_Xiong-er 的博客-CSDN博客_迷宫问题回溯java

问题分析

迷宫可以用二维数组来表示,假设起点是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]+" ");
		}
	}

}

如果有不正确的地方希望能够指出,一起进步~~~~~~~~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值