Java-Day-7(方法递归调用)

发布时间 2023-04-11 20:46:26作者: 朱呀朱~

Java-Day-7

方法递归调用

方法自己调用自己,每次调用传入不同的变量

  • jvm的内存,方法的递归调用

    T t1 = new T();
    t1.test(4);
    
    public void test(int n){
        if(n > 2){
            test(n - 1);
        }
        System.out.println("n =" + n); 
    }
    
    • 栈里执行 main 语句,在 new 时,指向堆内的空间
    • t1.test 执行方法时就会开辟新的独立的栈,栈内执行 test 方法的语句
    • 再次走到执行方法的时候就再开新的独立栈
    • 直到结束时,再一步步返回,若开新栈后还有语句,就在返回时把后面语句也都走完
  • 递归的重要规则

    • 执行一个方法时就创建一个新的受保护的独立空间,方法的局部变量是独立的,互不影响
    • 如果方法中使用的是引用类型变量 ( 数组,对象 ),就会共享该引用类型的数据
    • 递归必须向退出递归的条件逼近,否则就是无限递归了
    • 当一个方法执行完毕,或者遇到 return,谁调用,就返回给调用的那个
  • 练习题

    • 阶乘 ( factorial )

      public int factorial(int n){
          if(n == 1){
              return 1;
          } else {
              return factorial(n - 1) * n;
          }    
      }
      // 5 的阶乘:1*2*3*4*5
      
    • 斐波那契数 ( 1 1 2 3 5 8 ... )

      • 从 3 开始,后面每个数都是前两位数之和

      • if 1 || 2 —— return 1
        else return fibonacci ( n - 1 ) + fibonacci ( n - 2 )

    • 猴子吃桃

      • 一堆桃子,猴子每天吃其中一半另加一个,到第十天还没吃时,发现只有一个桃子了,求最初桃子数

      • 逆推递归,Day10:1,Day9:( Day10 + 1 ) * 2 = 4

        ​ Day8:( Day9 + 1 ) * 2 = 10 ......

      • if >=1 && <=9 return ( peach ( day+1 ) + 1 ) * 2

    • 走出迷宫

      • 0可以走;1是障碍物;2可以走但是已经走过了;3走过但是走不通是死路

      • 终点坐标点为2时,就表示有通路,可以退出了 ,否则继续找

      • 定走迷宫策略:下—>右—>上—>左

        public class Test {
            public static void main(String[] args) {
                int[][] map = new int[8][7];
                for (int i = 0; i < 7; i++){
                    map[0][i] = 1;
                    map[7][i] = 1;
                }
                for (int j = 0; j < 8; j++){
                    map[j][0] = 1;
                    map[j][6] = 1;
                }
                map[3][1] = 1;
                map[3][2] = 1;
                map[2][2] = 1;
                for (int i = 0; i < map.length; i++){
                    for (int j = 0; j < map[i].length; j++){
                        System.out.print(map[i][j] + " ");
                    }
                    System.out.println();
                }
        
                T t = new T();
                System.out.println("走完后的地图:");
                t.findway(map, 1, 1);
        
                for (int i = 0; i < map.length; i++){
                    for (int j = 0; j < map[i].length; j++){
                        System.out.print(map[i][j] + " ");
                    }
                    System.out.println();
                }
            }
        }
        // 寻路方法放类T中
        class T {
            public boolean findway(int[][] map, int i, int j) {
                if (map[6][5] == 2){ // 假定(6,5)为出口
                    return true;  // 找到出路了
                } else {
                    if (map[i][j] == 0){ // 没走过,可以走
                        // 假定可以走通
                        map[i][j] = 2;
                        // 找路策略
                        if (findway(map, i + 1, j)){ // 下
                            return true;
                        } else if (findway(map, i, j + 1)){ // 右
                            return true;
                        } else if (findway(map, i - 1, j)){ // 上
                            return true;
                        } else if (findway(map, i, j - 1)){ // 左
                            return true;
                        } else {
                            map[i][j] = 3; // 死路
                            return false; // 回溯到上一步
                        }
                    } else { // 1 , 2 , 3
                        return false;
                    }
                }
            }
        }
        
    • 汉诺塔

      • 把所有 A 塔上的盘都放到 C 塔上,始终保持小在上,大在下

        public class Test {
            public static void main(String[] args) {
                Tower tower = new Tower();
                tower.move(3, 'A', 'B', 'C');
            }
        }
        
        class Tower {
        //    a、b、c三个塔(a为初始,b为借助,c为终点)
            public void move(int num, char a, char b, char c){
                if(num == 1){
                    System.out.println(a + "->" + c);
                } else {
        //            如果有多个盘,可以看成两个,最下面一个,上面所有的(num - 1)看成一个,所有步骤都按照以下三个规律来做
        //            1. 先借助c,把上面的盘移动到b
                    move(num - 1, a, c, b);
        //            2. 把最下面的盘移动到c
                    System.out.println(a + "->" + c);
        //            3. 再借助a,把b塔的盘移动到c
                    move(num - 1, b, a, c);
                }
            }
        }
        
    • 八皇后问题

      • 8 * 8 格的国际象棋上摆放八个皇后,使所有皇后不处于同一列、同一行或同一斜线上,问有多少种摆法
      • 理论上应该创建二维数组,但实际上可以用一维数组来解决,即下标表示第几行,存放的数表示第几列