DFS-找出数组所有组合为target(元素可多次使用)

该代码示例展示了如何使用Java编写一个深度优先搜索(DFS)算法,找出数组中所有可能的组合,使得这些数字的和为目标值7,允许元素重复使用。优化版中引入了剪枝策略,通过排序数组并检查当前元素是否会导致和超过目标值,从而提高效率。
摘要由CSDN通过智能技术生成

题目:
找出[2,3,4,7]中所有组合target=7
example:[3,4]、[7]
注意:元素可以多次被使用,即[2,2,3]也可以即2可以被使用2

/**
 * Author:m
 * Date: 2023/04/08 10:46
 */
public class Target7AllowRepeat {
    private static final int TARGET = 7;
    public static void main(String[] args) {
        int[] array = new int[]{2, 3, 4, 7};
        List<List<Integer>> result = dfs(array);
        System.out.println(result);
    }

    private static List<List<Integer>> dfs(int[] array) {
        if (array == null) {
            return Lists.newArrayList();
        }

        List<List<Integer>> result = Lists.newArrayList();
        List<Integer> combine = Lists.newArrayList();
        int initIndex = 0;
        int sum = 0;
        recursion(result, combine, array, initIndex, sum);
        return result;
    }

    private static void recursion(List<List<Integer>> result, List<Integer> combine, int[] array, int initIndex, Integer sum) {

        // 1.终止条件
        if (sum > TARGET) {
            return;
        }

        // 2.小集合添加至大集合
        if (sum == TARGET) {
            result.add(Lists.newArrayList(combine));
            return;//sum已经等于target了,以tempList为基础的元素再去结合别的元素求和,只会越来越大于target,无需继续了
        }

        // 3.for循环
        for (int i = initIndex; i < array.length; i++) {
            // 3.1添加元素到小集合
            combine.add(array[i]);
            // 3.2递归(由于每一个元素可以重复使用,下一轮搜索的起点依然是 i,而不是i+1)
            recursion(result, combine, array, i, sum + array[i]);
            // 3.3回溯(小集合删除最后一个元素)
            combine.remove(combine.size() - 1);
        }
    }
}


优化

/**
 * Author:m
 * Date: 2023/04/08 10:53
 */
public class Target7AllowRepeatOptm {
    private static final int TARGET = 7;
    public static void main(String[] args) {
        int[] array = new int[]{2, 3, 3, 4, 7};
        Arrays.sort(array);
        List<List<Integer>> result = dfs(array);
        System.out.println(result);
    }

    private static List<List<Integer>> dfs(int[] array) {
        if (array == null) {
            return Lists.newArrayList();
        }

        List<List<Integer>> result = Lists.newArrayList();
        List<Integer> combine = Lists.newArrayList();
        int initIndex = 0;
        int sum = 0;
        recursion(result, combine, array, initIndex, sum);
        return result;
    }

    private static void recursion(List<List<Integer>> result, List<Integer> combine, int[] array, int initIndex, Integer sum) {

        // 1.终止条件
        if (sum > TARGET) {
            return;
        }

        // 2.小集合添加至大集合
        if (sum == TARGET) {
            result.add(Lists.newArrayList(combine));
            return;//sum已经等于target了,以tempList为基础的元素再去结合别的元素求和,只会越来越大于target,无需继续了
        }

        // 3.for循环
        for (int i = initIndex; i < array.length; i++) {
            // 3.0剪枝优化
            // 如果当前sum = 4,array[i] = 5, 那么sum + 5 > 7了。array是正序排序过的,后面的值只会越来愈大,sum加上他们只会比7更大,不可能为7了
            if (sum + array[i] > TARGET) {
                break;
            }
            // 3.1添加元素到小集合
            combine.add(array[i]);
            // 3.2递归(由于每一个元素可以重复使用,下一轮搜索的起点依然是 i,而不是i+1)
            recursion(result, combine, array, i, sum + array[i]);
            // 3.3回溯(小集合删除最后一个元素)
            combine.remove(combine.size() - 1);
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值