递归算法示例

递归算法示例

  1. 递归算法是指通过重复将问题分解为同类的子问题而解决问题的方法。递归就是在运行过程中不断调用自己,直到遇到终止条件,返回运算的结果。递归分为两个步骤,一是原问题要把计算结果传递给子问题,二是子问题求出结果后,把结果层层返回原问题。

  2. 阶乘求解

public class RecursionInstance {
    public static void main(String[] args) {
        print(4);
        System.out.println("n的阶乘:");
        int res = factor(4);
        System.out.println(res);
    }
    
    private static void print(int n) {
    	if (n > 2) {
            print(n - 1);
        }           
        System.out.println("n=" + n);
    }
    
    private static int factor(int n) {
        if (n == 0 || n == 1) {
            return 1;
        } else {
            return n * factor(n - 1);
        }
    }
}
  1. 全排列问题,从第一个数字起,每个数字分别与后面的数字进行交换;去重的全排列就是第一个数字起,每个数字分别与后面非重复出现的数字交换。
public class FullPermutation {
    //统计排列的个数
    private static int count;
    
    public static void main(String[] args) {
        //n位数字的全排列有n!种情况
        int[] arr = {1, 2, 3, 4, 5};
        permutation(arr, 0, 4);
    }
    
    /**
     * 递归输出排列数
     */
    private static void permutation(int[] arr, int low, int high) {
        if(low == high) {
            count++;
            System.out.println("第" + count + "个排列:");
            for(int i=0;i<=high;i++) {
                System.out.println(arr[i]);
            }
            System.out.println();
        }else{
            //每次i从low增长到high,high值固定不变
            for(int i=low;i<=high;i++) {
                swap(arr, i, low);
                permutation(arr, low+1, high);
                swap(arr, i, low);
            }
        }
    }
    
    private static void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}
  1. 组合问题
public class Combination {
    public static void main(String[] args) {
        combine();
    }
    
    /**
     * 对数组下标进行编码,1 - a,2 - b, 3 - ab, 4 - c...
     */
    private static void combine() {
        String[] arr = {"a", "b", "c", "d", "e", "f", "g"};
        int n = arr.length;
        int nBit = 1 << n;
        System.out.println("全组合结果的个数为:" + nBit);
        for(int i=0;i<nBit;i++) {
            System.out.print("组合数值" + i + "对应编码为:");
            for(int j=0;j<n;j++) {
                int tmp = 1 << j;
                if((tmp & i) != 0) {
                    System.out.print(arr[j]);
                }
            }
            System.out.print();
        }
    }
}
  1. 汉诺塔问题
public class HanoiTower {

    public static void main(String[] args) {
        hanoiTower(5, 'A', 'B', 'C');
    }

    //汉诺塔移动方法
    private static void hanoiTower(int num, char a, char b, char c){
        if(num == 1){
            System.out.println("第1个盘从" + a + "=>" + c);
            return;
        }

        //如果盘的数目大于1,总是可以看做有两个盘:最下边的盘和上面的所有盘
        //1.先把上面所有的盘从A移到B,移动过程中会使用到C
        hanoiTower(num-1, a, c, b);
        //2.把最下面的盘从A移动到C
        System.out.println("第" + num + "个盘从" + a + "=>" + c);
        //3.把B中的所有盘移到C,移动过程中会使用到A
        hanoiTower(num-1, b, a, c);
    }
}
  1. 八皇后问题
public class Queen {
    //皇后的个数
    private final int MAX_QUEUES = 8;
    //使用一维数组保存皇后的位置,数组下标表示行坐标,也就是第几个皇后,数组的值表示列坐标
    private int[] arr = new int[MAX_QUEUES];
    private static int count;
    
    public static void main(String[] args) {
    	Queen queen = new Queen();
        queen.check(0);
        System.out.printf("一共有%d种解法\n", count);
    }
    
    /**
     * 放置第n个皇后
     */
    private void check(int n) {
        if (MAX_QUEENS == n) {
            print();
            return;
        }
        
        //依次放入皇后,判断是否冲突
        for(int i=0;i<MAX_QUEUES;i++) {
            //先把当前皇后n放到该行的第一列
            arr[n] = i;
            if(judge(n)) {
                //冲突则接着循环,不冲突则接着放n+1个皇后
                check(n+1);
            }
        }
    }
    
    /**
     * 判断是否冲突
     */
    private boolean judge(int n) {
        for(int i=0;i<n;i++) {
            //第n个皇后和前面n-1个皇后在一列或者在同一个斜线上则冲突
            if(arr[i] == arr[n] || Math.abs(n-i) == Math.abs(arr[n] - arr[i])) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 输出皇后摆放的位置
     */
    private void print() {
        count++;
        for(int i:arr) {
            System.out.print(i + " ");
        }
        System.out.println();
    }
}
  1. 迷宫问题
public class MiGong {
    public static void main(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][1] = 1;
        map[3][2] = 1;
        //输出地图
        printMap(map);
        //使用递归回溯给小球找路
        setWay(map, 1, 1);
        System.out.println("输出小球走过的路:");
        printMap(map);
    }
    
    /**
     * 使用递归回溯来给小球找路
     * 1.(i,j)表示从地图的哪个位置开始出发(1,1)
     * 2.如果小球能到map[6][5]位置,则说明通道找到
     * 3.约定:当map[i][j]为0表示该点没有走过,1表示墙,2表示通道可以走,3表示该点已经走过,走不通
     * 4.在走迷宫时,需要确定一个策略,下->右->上->左,如果该点走不通,再回溯
     * @param map 地图
     * @param i 出发点置的i
     * @param j 出发点位置的j
     * @return 如果找到通路返回true,否则返回false
     */
    private 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{
                return false;
            }
        }
    }
    
    /**
     * 输出地图
     */
    private static void printMap(int[][] map){
        for(int i=0;i<8;i++){
            for(int j=0;j<7;j++){
                System.out.print(map[i][j] + "  ");
            }
            System.out.println();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐江小鱼

知识创造财富,余额还是小数

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值