回溯法-递归实现1 -- 记录自己刷题(拾人牙慧而与)

目录

1 问题描述:如何实现从n个数字放到k个桶中,并且每个桶中都有数字

2 求取数组的子集:给定一个数组,输出它的所有子集


参考资料labuladuo算法:

回溯算法牛逼:集合划分问题 :: labuladong的算法小抄

1 问题描述:如何实现从n个数字放到k个桶中,并且每个桶中都有数字

以数字的视角,每个数字尝试放入桶当中

public static void main(String[] args) {

        //
        int n = 5;
        int k = 3;
        int[] nums = new int[5];
        List<List<Integer>> buckets = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            nums[i] = i + 1;
        }
        for(int i=0;i<k;i++) {
            buckets.add(new ArrayList<>());
        }
        new Main().traverse(nums, 0, buckets);
        System.out.println("Hello world");

    }

    void traverse(int[] nums, int idx, List<List<Integer>> buckets) {
        if (idx >= nums.length) {
//返回合法的分配方法
            if(validBucket(buckets, 0)) {
                System.out.println(buckets.toString());
            }

            return;
        }
        for (int i = 0; i < buckets.size(); i++) {
            //简单剪枝,减少遍历次数
            if(!validBucket(buckets, nums.length - idx)) {
                return;
            }
            List<Integer> bucket = buckets.get(i);
            bucket.add(nums[idx]);

            traverse(nums, idx+1, buckets);

            bucket.remove(bucket.size()-1);
        }
    }
    boolean validBucket(List<List<Integer>> buckets, int leftNum) {

        for(int i=0;i<buckets.size();i++) {
            if(buckets.get(i).size() <=0) {
                leftNum--;
            }
        }
        return leftNum>=0;
    }

2 求取数组的子集:给定一个数组,输出它的所有子集

方法一: 数学归纳法-每次的结果可以根据上一次的结果得到,代码如下:

void traverse2(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        result.add(new ArrayList<>());
        for(int i=0;i<nums.length;i++) {
            int size = result.size();
            for(int j=0;j<size;j++) {
                List<Integer> element = new ArrayList<>();
                result.get(j).forEach(o -> {
                    element.add(o);
                });
                element.add(nums[i]);
                System.out.println(element.toString());
                result.add(element);
            }
        }
    }

方法二:回溯法实现-每次选择元素是否加入到相关的子集中

/**
     * 
     * @param nums -- 数组
     * @param index -- 数组下标,需要考虑是否加入的数组元素下标
     * @param result -- 最后的结果
     */
    void traverse(int[] nums,int index, List<Integer> result) {
        System.out.println(result.toString());
        for(int i=index;i<nums.length;i++) {
                result.add(nums[i]);

                traverse(nums, i + 1, result);

                result.remove(result.size()-1);
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值