N个数字的所有可能组合以求和

时间:2019-04-14 01:55:54

标签: java algorithm data-structures

我必须编写一个程序,给定ntargetmax,返回所有大小为n的数字组合,总和为target,其中任何数字都不能大于max

示例:

target = 3
max = 1
n = 4

输出:

[0, 1, 1, 1]
[1, 0, 1, 1]
[1, 1, 0, 1]
[1, 1, 1, 0]

这是一个非常简单的示例,但是对于更复杂的情况,可能会有很多可能的组合。

我正在寻找任何算法线索,但是Java实现将是完美的。

3 个答案:

答案 0 :(得分:1)

我的想法是,只要我们超出条件之一,就以BFS样式修剪生成排列。另一个技巧是,一旦达到目标,就需要用零填充其他所有内容。这是一个python实现,因为我现在没有安装Java。翻译应该很容易

def sums(n, target, max, arr=[], sum=0):
    if len(arr) > n or sum > target: 
        return 
    if sum == target:
        print arr + [0 for _ in range(n - len(arr))]
        return 
    for i in range(max) + 1: 
        sums(n, target, max, arr + [i], sum + i)

示例sums(4, 3, 1)

  

[0,1,1,1] [1,0,1,1] [1,1,0,1] [1,1,1,0]

答案 1 :(得分:1)

以下是Java版本:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<int[]> solutions = generate(3, 1, 4);
        for(int[] c: solutions) {
            System.out.println(Arrays.toString(c));
        }
    }  

    public static List<int[]> generate(int target, int max, int n) {
        return generate(new ArrayList(), new int[0], target, max, n);
    }

    private static List<int[]> generate(List<int[]> solutions, 
            int[] current, int target, int max, int n) {        
        int sum = Arrays.stream(current).sum();
        if (current.length == n) {
            if (sum == target) {
                solutions.add(current);
            }
            return solutions;
        }
        if (sum > target) {
            return solutions; 
        }
        for(int i=0; i <= max; i++) {
            int[] next = Arrays.copyOf(current, current.length + 1);
            next[current.length] = i; 
            generate(solutions, next, target, max, n);
        }
        return solutions; 
    }
}

答案 2 :(得分:1)

这可能会浪费资源:但这是我的解决方法

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Combinations {
    public static void main(String[] args) {

       List<Integer[]> finalPatternList = getCombinations(6, 10, 12);
    }

    static List<Integer[]> getCombinations(int n, int target, int max) {

        /*
            first generate all the combinations on the given n
         */

        List<Integer[]> allCombinationsList = new ArrayList<>();

        //generate the digits list
        List<Integer> digitList = new ArrayList<Integer>();
        for (int i = 0; i <= max; i++) {
            digitList.add(i);
        }
        //generate the number system
        int powerBase = digitList.size();
        int maxPower = n ;
        int totalCombinations = (int) Math.pow(powerBase, maxPower);

        //generating default array
        for (int i = 0; i < totalCombinations; i++) {
            Integer pattern[] =new Integer[n];;
            allCombinationsList.add(pattern);
        }

        //filling the Columns one by one

        for (int i =n  ; i >= 1 ; i -- ){
            int currentColumn = i - 1;
            int noOfIterations =(int) Math.pow(max + 1,  n - i);
            populateRows(allCombinationsList ,digitList ,currentColumn ,noOfIterations );
        }
         /*
           example :

              [0, 0, 0, 0]
              [0, 0, 0, 1]
              [0, 0, 1, 0]
              [0, 0, 1, 1]
              [0, 1, 0, 0]
              [0, 1, 0, 1]
              [0, 1, 1, 0]
              [0, 1, 1, 1]
              ............

              current row variable is the array index
              if currentRow = 3,
                 pattern 1 - its 0
                 pattern 2 - its 1
                 pattern 3 - its 0
              if currentRow = 2 ,
                 pattern 1 - its 0
                 pattern 2 - its 0
                 pattern 3 - its 1


              iterations means the number of consecutive digits appear on each column
              in column 1 - its 1
              in column 2 - its 2
              in column 3 - its 4


         */




        /*
            select the patterns that match the target
         */

        List<Integer[]> finalPatternList = new ArrayList<>();
        for (Integer[] currentArray : allCombinationsList){

            int sum = 0 ;
            for (int i =0 ; i < currentArray.length ; i++ ){
                sum +=currentArray[i] ;
            }
            if (sum == target) finalPatternList.add(currentArray);

        }
        for (Integer a[] : finalPatternList) {
            System.out.println(Arrays.toString(a));
        }

        return finalPatternList;


    }

    static void populateRows(List<Integer[]> combinationList, List<Integer> digitList, int currentColumn, int iterations) {

        int combinationListPosition = 0;
        while (combinationListPosition < combinationList.size()) {
            int digitListPosition = 0;
            while (digitListPosition < digitList.size()) {
                int currentIteration = 0;
                while (currentIteration < iterations) {

                    if (combinationListPosition == combinationList.size()){
                        // end the loop when all combinations are filled
                        System.out.println();
                         return;
                    }

                    combinationList.get(combinationListPosition)[currentColumn] = digitList.get(digitListPosition);
                    currentIteration++;
                    combinationListPosition ++ ;
                }
                digitListPosition ++ ;
            }
        }




    }
}