递归的return和八皇后问题
一、递归的return问题
1.1递归概念:
方法递归,就是fun(fun(fun(fun()+1)+1)+1)
在方法中调用方法本身,每次的操作步骤相同
1.2问题描述:
在里层return执行完毕之后,会执行外层的return 返回值,导致最后的返回值不对
1.3问题解决:
方法1.外层直接return 方法名(参数); 因为不是return的该层方法的返回值,而是retrun里层方法的返回值,return套return最终它返回值是最里层的
方法2.不要返回值;
方法3.返回值为引用数据类型,因为一直返回的是地址。里面的内容发生改变就是变了。
1.4递归的使用案例:
*数学黑洞6174
//已知:一个任意的四位正整数。将数字重新组合成一个最大的数和最小的数
//相减,重复这个过程,最多七步,必得6174。即:7641-1467=6174。将永远出不
//来。
//求证:所有四位数数字(全相同的除外),均能得到6174。输出掉进黑洞的
//步数。
for (int i = 1000; i <= 9999; i++) {
System.out.println("=========================");
System.out.println(i);
System.out.println(mathBH(i));
System.out.println("=========================");
}
--------------------------------------------------------------------
static int count=0;
private static int mathBH(int i) {
int ge=i%10;
int shi=i/10%10;
int bai=i/100%10;
int qian=i/1000;
if(ge==shi&&ge==bai&&ge==qian){
return -1;
}else {
int[] num13={ge,shi,bai,qian};
Arrays.sort(num13);
int max1=num13[3]*1000+num13[2]*100+num13[1]*10+num13[0];
int min1=num13[0]*1000+num13[1]*100+num13[2]*10+num13[3];
int num=max1-min1;
count++;
if(num==6174){
System.out.println(count);
int countLast=count;
count=0;
return countLast;
}else {
return mathBH(num); //注意这里的技巧,直接return方法本身的返回值,那么后面就不存在,多余的return问题了。
}
}
}
1.5递归的使用--------回溯算法:
原理:调用自身方法,有返回值,且返回值中不含有return;
真正产生回溯现象的原因是:参数的作用域问题,里层方法的参数n作用域只在里层,当里层的方法执行完成的时候,继续执行外层的方法,外层的方法的参数还是外层传入的n,内外层的n只是在表现形式上都叫n,其实本质上对JVM来说里外层的n本质是不一样的。
联想内存图,每调用一个方法就会有一个方法进栈,在最上面的方法(n=8)执行完成后,就会弹栈,然后执行现在最高层的代码,而这个代码里面的n是7*
二、八皇后问题
2.1八个皇后问题案例(问题分析中注意算法和内存图的结合):
八皇后问题
//在8×8 的国际象棋盘上,放置八个皇后,使任何一个皇后都不能吃掉另一
//个。国际象棋规则中,皇后可以吃到任何一个与他在同一行、同一列或者同一斜
//线上的敌方棋子,所以八皇后问题的所有解满足:8 个皇后都不在同一行、同一
//列,或者同一斜线上。
//输出所有的解。
//提示:使用递归。
public class Test {
static int[] queens = new int[8]; //表示每一行皇后的纵坐标
static int solveNum = 1; //统计解的数量
public static void main(String[] args) {
put(0);
}
//判断在之前的基础上在第n行放第m列是否可行
public static boolean canPut(int n, int m){
//判断是否有在同一列的
for(int i = 0; i<n; i++){
if (queens[i] == m) return false;
}
//判断是否有在左上-->右下对角线
for(int i = 0; i<n; i++){
if (queens[i] - i == m - n) return false;
}
//判断是否有在右上-->左下对角线
for(int i = 0; i<n; i++){
if (queens[i] + i == m + n) return false;
}
return true;
}
//表示尝试放置第n行的皇后
public static void put(int n){
if (n == 8){
System.out.println("=============================");
System.out.println(solveNum++);
printQueen();
return;
}
for(int i = 0; i<queens.length; i++){
if (canPut(n, i)){
queens[n] = i;
put(n+1);
queens[n] = 0; //注意这里的n是外层的n,正因为外层方法的n
//是外层的n,所以产生了回溯现象
}
}
}
public static void printQueen(){
for(int i = 0; i<queens.length; i++){
for(int j = 0; j<queens.length; j++){
if (queens[i] == j){
System.out.print("* ");
}else{
System.out.print("0 ");
}
}
System.out.println();
}
}
}