Java 给定一个数字和一个数组,找出所有可能的组合,求和为给定的数字

Java 给定一个数字和一个数组,找出所有可能的组合,求和为给定的数字,java,algorithm,Java,Algorithm,我在一次采访中被问及这个项目。任务被赋予一个整数数组作为输入,另一个数字是target,在数组中找到所有可能的组合,这些组合的总和就是给定的目标 示例: array = [1,2,1,1,1] target = 3 expected result : [1,2],[1,1,1],[2,1],[2,1] 我想出了以下代码: public static void main(String args[]) { Integer[] numbers = { 1, 2, 1, 1, 1 };

我在一次采访中被问及这个项目。任务被赋予一个整数数组作为输入,另一个数字是
target
,在数组中找到所有可能的组合,这些组合的总和就是给定的目标

示例:

array = [1,2,1,1,1]
target = 3

expected result : [1,2],[1,1,1],[2,1],[2,1]
我想出了以下代码:

public static void main(String args[]) {
    Integer[] numbers = { 1, 2, 1, 1, 1 };
    int target = 3;
    process(numbers, target);
}

private static void process(Integer[] numbers, int target) {
    for (int i = 0; i < numbers.length; i++) {
        int sum = 0;

        for (int j = i; j < numbers.length; j++) {
            sum += numbers[j];
            if (sum == target) {
                for (int k = i; k <= j; k++) {
                    System.out.print(numbers[k] + " ");
                }
                System.out.println();
            }
        }
    }
}
publicstaticvoidmain(字符串参数[]){
整数[]数={1,2,1,1,1};
int目标=3;
过程(数量、目标);
}
私有静态无效进程(整数[]数字,int目标){
for(int i=0;i对于(int k=i;k您可以使用回溯执行类似的操作:

  public List<List<Integer>> combinationSum(int[] candidates, int target) {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();
    Arrays.sort(candidates);
    int start = 0; 

    backtrack(candidates, target, start, result, temp);

    return result;
}

public void backtrack(int[] candidates, int remaining, int start, List<List<Integer>> result, List<Integer> temp) {
    if(remaining == 0) { 
        result.add(new ArrayList<>(temp)); 
        return;
    }

    if(remaining < 0) { return; }

    for(int i = start; i < candidates.length; i++) {
        temp.add(candidates[i]);
        backtrack(candidates, remaining - candidates[i], i, result, temp);
        temp.remove(temp.size() - 1);
    }
}
公共列表组合总和(int[]候选项,int目标){
列表结果=新建ArrayList();
List temp=new ArrayList();
数组。排序(候选);
int start=0;
回溯(候选人、目标、开始、结果、临时);
返回结果;
}
公共无效回溯(int[]候选项、int剩余项、int开始项、列表结果、列表临时项){
如果(剩余==0){
结果.添加(新ArrayList(temp));
回来
}
if(剩余<0){return;}
for(int i=start;i

您可以阅读有关回溯和类似方法的更多信息。

这是使用递归的最佳选择:

public static void main(String args[]) {
    Integer[] numbers = { 1, 2, 1, 1, 1 };
    int target = 3;

    for(int i = 0; i < numbers.length; i++) {
        recurseAdd(i, numbers, new ArrayList<Integer>(), 0, target);
    }
}

private static void recurseAdd(int currentIndex, Integer[] numbers, List<Integer> usedNumbers, int sum, int target) {
    if (currentIndex >= numbers.length) {
        return;
    }

    sum = sum + numbers[currentIndex];
    usedNumbers.add(numbers[currentIndex]);

    if (sum == target) {
        System.out.println(usedNumbers);
        return;
    }

    if (sum > target) {
        return;
    }

   for (int i = currentIndex + 1; i < numbers.length; i++) {
        recurseAdd(i, numbers, new ArrayList<>(usedNumbers), sum, target);
    }
}
publicstaticvoidmain(字符串参数[]){
整数[]数={1,2,1,1,1};
int目标=3;
for(int i=0;i=number.length){
回来
}
总和=总和+数字[当前索引];
添加(数字[currentIndex]);
如果(总和==目标){
System.out.println(使用的编号);
回来
}
如果(总和>目标){
回来
}
对于(int i=currentIndex+1;i
您的预期结果是错误的。它应该是:[1,2]、[1,1,1]、[2,1]、[2,1]、[1,1,1]、[1,1,1](不一定按该顺序排列)。这是因为最后三个1中的任何一个都可以替换为前一个1,并且加起来仍然是3。这是动态规划的一个很好的候选者?您的算法只考虑连续的子数组,但您的问题陈述似乎是关于任意组合。我将对数组进行位屏蔽,就像-在第一次迭代中,使用
数字[0]
,在第二个
数字[1]
,然后
数字[0]
数字[1]
等等-检查每个掩蔽是否与目标匹配。甚至我上面的预期结果也是错误的。[2,1]对应该出现三次,因为在2:[1,2]、[1,1,1]、[2,1]、[2,1]、[1,1]、[1,1]之后有三个1]