简体   繁体   English

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

[英]Print all combinations of a number as a sum of candidate numbers

Does anyone have a solution to the following question? 有人对以下问题有解决方案吗? It seems like a classic problem, but I haven't found any good answers online yet. 这似乎是一个经典问题,但是我还没有在网上找到任何好的答案。

Given a target number, and a series of candidate numbers, print out all combinations, so that the sum of candidate numbers equals to the target. 给定目标编号和一系列候选编号,请打印出所有组合,以便候选编号的总和等于目标。

Here order is not important, so don't print the duplicated combination. 此处的顺序并不重要,因此请勿打印重复的组合。

eg target is 7, candidate is 2,3,6,7 output should be 7 and 3+2+2 (but not print 2+3+2, 2+2+3) 例如目标为7,候选为2、3、6、7,输出应为7和3 + 2 + 2(但不打印2 + 3 + 2、2 + 2 + 3)

Since you have to print all the combinations, you can employ a general complete search program using recursion. 由于必须打印所有组合,因此可以使用递归使用常规的完整搜索程序。 For example, this code solves the problem and prints all such combinations. 例如, 此代码解决了问题,并打印了所有此类组合。

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);
        }
    }
}

The only pre condition to using the function printCombinations is that the array arr must not contain duplicates. 使用函数printCombinations的唯一前提条件是数组arr不能包含重复项。 And if it contains duplicates, we can easily remove them using a Set. 而且,如果其中包含重复项,我们可以使用Set轻松删除它们。

In the code N is required target. 在代码中N是必需的目标。 And arr is the set of candidate numbers. 而arr是候选编号的集合。 for N=7 and arr[] = {2, 3, 6, 7} the code prints: 对于N = 7和arr [] = {2,3,6,7},代码将输出:

2 2 3 
7 

Have a look at this code which uses backtracking. 看一下使用回溯的代码。

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);
}

If the candidate number has to be used only once, then just change the first recursive call and use 'counter+1' instead of 'counter'. 如果候选号码仅需使用一次,则只需更改第一个递归调用并使用“ 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);


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM