Algorithm 将数字的所有组合打印为候选数字的总和

Algorithm 将数字的所有组合打印为候选数字的总和,algorithm,Algorithm,有人能解决以下问题吗?这似乎是一个经典的问题,但我还没有在网上找到任何好的答案 给定一个目标编号和一系列候选编号,打印出所有组合,使候选编号的总和等于目标编号 这里的顺序并不重要,所以不要打印重复的组合 e、 目标是7,候选人是2,3,6,7 输出应为7和3+2+2(但不是打印2+3+2、2+2+3) 由于必须打印所有组合,因此可以使用递归使用通用的完整搜索程序。例如,解决问题并打印所有这些组合 import java.io.*; import java.math.*; import java.

有人能解决以下问题吗?这似乎是一个经典的问题,但我还没有在网上找到任何好的答案

给定一个目标编号和一系列候选编号,打印出所有组合,使候选编号的总和等于目标编号

这里的顺序并不重要,所以不要打印重复的组合

e、 目标是7,候选人是2,3,6,7 输出应为7和3+2+2(但不是打印2+3+2、2+2+3)


由于必须打印所有组合,因此可以使用递归使用通用的完整搜索程序。例如,解决问题并打印所有这些组合

import java.io.*;
import java.math.*;
import java.util.*;

class Solution{ 
    public static void main(String[] args)throws java.lang.Exception{
        new Solution().run();
    }

    int N = 7;
    int[] arr = {2, 3, 6, 7};
    int[] vals = new int[N];;

    void run(){
        printCombinations(N, 0, 0);
    }

    // from : consider numbers in arr from index "from"
    // index: add new number in array vals at index "index"
    void printCombinations(int target, int from, int index){
        if(target==0){
            for(int i=0; i<index; i++){
                System.out.print(vals[i] + " ");
            }
            System.out.println();
        }else if(target<0 || from>=arr.length){
            return;
        }else{
            vals[index] = arr[from];
            // take arr[from] in set
            printCombinations(target-arr[from], from, index+1);

            // dont take arr[from] in set
            printCombinations(target, from+1, index);
        }
    }
}

看看这个使用回溯的代码

public static void main (String[] args) {

    int[] arr = {2,3,6,7};
    int target = 9; 

    ArrayList<Integer> result = new ArrayList<Integer>();

    printCombinations(result, arr, target, 0);
}

private static void printCombinations(ArrayList<Integer> result, int[] arr, int target, int counter) {

    if(target == 0) {
        System.out.println(result);
        return;
    }

    if(target < 0 || counter>=arr.length) {
        return;
    }

    result.add(arr[counter]);
    printCombinations(result, arr, target-arr[counter], counter);

    result.remove(result.indexOf(arr[counter]));
    printCombinations(result, arr, target, counter+1);
}
publicstaticvoidmain(字符串[]args){
int[]arr={2,3,6,7};
int目标=9;
ArrayList结果=新建ArrayList();
打印组合(结果、arr、目标、0);
}
私有静态void打印组合(ArrayList结果、int[]arr、int目标、int计数器){
如果(目标==0){
系统输出打印项次(结果);
返回;
}
如果(目标<0 | |计数器>=阵列长度){
返回;
}
结果。添加(arr[计数器]);
打印组合(结果、arr、目标arr[计数器]、计数器);
result.remove(result.indexOf(arr[计数器]);
打印组合(结果、arr、目标、计数器+1);
}
如果候选号码只需使用一次,则只需更改第一个递归调用,并使用“counter+1”而不是“counter”

private static void printCombinations(ArrayList<Integer> result, int[] arr, int target, int counter) {

    if(target == 0) {
        System.out.println(result);
        return;
    }

    if(target < 0 || counter>=arr.length) {
        return;
    }

    result.add(arr[counter]);
    printCombinations(result, arr, target-arr[counter], counter+1);

    result.remove(result.indexOf(arr[counter]));
    printCombinations(result, arr, target, counter+1);


}
私有静态void打印组合(ArrayList结果、int[]arr、int目标、int计数器){
如果(目标==0){
系统输出打印项次(结果);
返回;
}
如果(目标<0 | |计数器>=阵列长度){
返回;
}
结果。添加(arr[计数器]);
打印组合(结果、arr、目标arr[计数器]、计数器+1);
result.remove(result.indexOf(arr[计数器]);
打印组合(结果、arr、目标、计数器+1);
}

这是子集和问题,它是一个经典的动态规划问题。你可以用谷歌搜索。这是目前为止对这个问题的最好答案。
private static void printCombinations(ArrayList<Integer> result, int[] arr, int target, int counter) {

    if(target == 0) {
        System.out.println(result);
        return;
    }

    if(target < 0 || counter>=arr.length) {
        return;
    }

    result.add(arr[counter]);
    printCombinations(result, arr, target-arr[counter], counter+1);

    result.remove(result.indexOf(arr[counter]));
    printCombinations(result, arr, target, counter+1);


}