数据结构与算法Day04递归

一、递归的概念与回顾

1.递归

递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

2.回顾

(1)阶乘计算

思路分析:
写一个方法,传入一个n值,计算n值的阶乘
递归需要一个末值,也就是执行最后的值,在阶乘中为1
如果此时n不为1,就返回n乘factorical(--n)
public int factorial(int n){
        if(n == 0){
            return 0;
        }
        if(n == 1){
            return 1;
        }else {//这里factorial(--n),如果传入的是n--,那么根据传参规则,就会把n传递进去,就会形成死循环
            return n * factorial(--n);
        }
    }

(2)打印问题

public void test(int i){
        if(i > 2){
            test(i - 1);
        }
        System.out.println("i = "+i);
    }

询问输出什么?

根据递归的性质可以看出,如果i>2,那就会一直调用test方法,直到i==2,那么i==2就是该递归的末值,所以输出为i = 2  ====>(一直到)  i = i;

二、迷宫问题

1.迷宫路径查找

思路分析:
1.传入迷宫地图的数组,迷宫上小球的初始位置数组,迷宫终点位置数组
2.如果当前小球位置等于终点位置,那么说明已走完
3.如果当前小球位置不等于终点位置,那么就让他行走
4.根据终点位置与当前位置的关系,设置行走的优先级顺序:
5.如果终点的x值大于当前x值,那就向下走,如果终点y值大于当前y值,那就向右走
6.用2代表走过的路,1代表墙,0代表可以走的路
7.拓展:(1)如果走入了死胡同内,那么就原路返回一个值,并将死胡同的地方设置为3
      (2)返回一位后,判断其他位置,如果还是死胡同,继续返回,反复
public void findWay(int[][] maps, int[] start, int[] end) {
        //结束条件
        if (start[0] == end[0] && start[1] == end[1]) {
            return;
        } else {//优先上下,其次左右
            if (start[0] > end[0]) {//当前x值大于终点x值,那向上移动
                if (maps[start[0] - 1][start[1]] == 0) {
                    start[0] = start[0] - 1;
                    maps[start[0]][start[1]] = 2;
                    findWay(maps, start, end);
                } else if (maps[start[0] - 1][start[1]] == 1 || maps[start[0] - 1][start[1]] == 3) {
                    if (start[1] > end[1]) {
                        if (maps[start[0]][start[1] - 1] == 0) {
                            start[1] = start[1] - 1;
                            maps[start[0]][start[1]] = 2;
                            findWay(maps, start, end);
                        } else if (maps[start[0]][start[1] - 1] == 1 || maps[start[0]][start[1] - 1] == 3) {
                            maps[start[0]][start[1]] = 3;
                            start[1] = start[1] + 1;
                            findWay(maps, start, end);
                        }
                    } else if (start[1] <= end[1]) {
                        if (maps[start[0]][start[1] + 1] == 0) {
                            start[1] = start[1] + 1;
                            maps[start[0]][start[1]] = 2;
                            findWay(maps, start, end);
                        } else if (maps[start[0]][start[1] + 1] == 1 || maps[start[0]][start[1] + 1] == 3) {
                            maps[start[0]][start[1]] = 3;
                            start[1] = start[1] - 1;
                            findWay(maps, start, end);
                        }
                    }
                }
            } else if (start[0] <= end[0]) {
                if (maps[start[0] + 1][start[1]] == 0) {
                    start[0] = start[0] + 1;
                    maps[start[0]][start[1]] = 2;
                    findWay(maps, start, end);
                } else if (maps[start[0] + 1][start[1]] == 1) {
                    if (start[1] > end[1]) {
                        if (maps[start[0]][start[1] - 1] == 0) {
                            start[1] = start[1] - 1;
                            maps[start[0]][start[1]] = 2;
                            findWay(maps, start, end);
                        }
                    } else if (start[1] <= end[1]) {
                        if (maps[start[0]][start[1] + 1] == 0) {
                            start[1] = start[1] + 1;
                            maps[start[0]][start[1]] = 2;
                            findWay(maps, start, end);
                        }
                    }
                }
            }
            //移动的
        }

    }

使用我的方法会显得代码非常复杂,又臭又长,所以根据老师讲述,进行修改后

2.精简版迷宫寻路

思路分析:传入地图的二维数组,当前x,y坐标以及最后的终点位置
1.设置墙为1,可以走的路为0,走过的路为2,如果地图上的终点位置为2,那么表示走完
2.走路优先级:下右上左
3.每次判断能不能走,能走返回true
4.如果此时走进死胡同,那便回溯,将当前值置为3,返回false,重新找路
public static boolean findWay2(int[][] maps,int x,int y,int[] end){
        if(maps[end[0]][end[1]] == 2){
            return true;
        }else {
            if(maps[x][y] == 0) {
                maps[x][y] = 2;
                if (findWay2(maps, x + 1, y, end)) {
                    return true;
                } else if (findWay2(maps, x, y + 1, end)) {
                    return true;
                } else if (findWay2(maps, x - 1, y, end)) {
                    return true;
                } else if (findWay2(maps, x, y - 1, end)) {
                    return true;
                } else {
                   maps[x][y] = 3;
                   return false;
                }
            }else {
                return false;
            }
        }
    }

三、八皇后

思路分析:
1.实现八皇后问题,就是在八乘八的棋盘上,每一行放一个皇后,皇后不能重行,不能重列,不能重斜线
2.使用一维数组实现,数组中的每个元素都不能相同,且每两个元素直接不能相连,即不能1,2这样
3.需要一个计数属性,用于计算实现的八皇后排序次数
public class EightQueen {

    public static void main(String[] args) {
        new EightQueen().check(0);
        System.out.println(count);
    }
    //创建输出结果集
    private int[] result = new int[8];
    private static int judgeCount = 0;
    private static int count = 0;
    //写出遍历方法
    public void list(){
        System.out.print("[\t");
        for (int i:result) {
            System.out.print(i + "\t");
        }
        System.out.print("]");
        System.out.println();
        count++;
    }

    //八皇后问题
    /*
    思路分析:
    1.实现八皇后问题,就是在八乘八的棋盘上,每一行放一个皇后,皇后不能重行,不能重列,不能重斜线
    2.使用一维数组实现,数组中的每个元素都不能相同,且每两个元素直接不能相连,即不能1,2这样
    3.需要一个计数属性,用于计算实现的八皇后排序次数
     */
    //编写一个方法,放置第n个皇后
    //特别注意: check 是 每一次递归时,进入到check中都有  for(int i = 0; i < max; i++),因此会有回溯
    private void check(int n) {
        if(n == result.length) {  //n = 8 , 其实8个皇后就既然放好
            list();
            return;
        }

        //依次放入皇后,并判断是否冲突
        for(int i = 0; i < result.length; i++) {
            //先把当前这个皇后 n , 放到该行的第1列
            result[n] = i;
            //判断当放置第n个皇后到i列时,是否冲突
            if(judge(n)) { // 不冲突
                //接着放n+1个皇后,即开始递归
                check(n+1); //
            }
            //如果冲突,就继续执行 array[n] = i; 即将第n个皇后,放置在本行得 后移的一个位置
        }
    }

    //查看当我们放置第n个皇后, 就去检测该皇后是否和前面已经摆放的皇后冲突
    /**
     *
     * @param n 表示第n个皇后
     * @return
     */
    private boolean judge(int n) {
        judgeCount++;
        for(int i = 0; i < n; i++) {
            // 说明
            //1. array[i] == array[n]  表示判断 第n个皇后是否和前面的n-1个皇后在同一列
            //2. Math.abs(n-i) == Math.abs(array[n] - array[i]) 表示判断第n个皇后是否和第i皇后是否在同一斜线
            // n = 1  放置第 2列 1 n = 1 array[1] = 1
            // Math.abs(1-0) == 1  Math.abs(array[n] - array[i]) = Math.abs(1-0) = 1
            //3. 判断是否在同一行, 没有必要,n 每次都在递增
            if(result[i] == result[n] || Math.abs(n-i) == Math.abs(result[n] - result[i]) ) {
                return false;
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值