繁体   English   中英

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

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

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

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

此处的顺序并不重要,因此请勿打印重复的组合。

例如目标为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);
        }
    }
}

使用函数printCombinations的唯一前提条件是数组arr不能包含重复项。 而且,如果其中包含重复项,我们可以使用Set轻松删除它们。

在代码中N是必需的目标。 而arr是候选编号的集合。 对于N = 7和arr [] = {2,3,6,7},代码将输出:

2 2 3 
7 

看一下使用回溯的代码。

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

如果候选号码仅需使用一次,则只需更改第一个递归调用并使用“ 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