我必须写一个程序,给出n
,target
和max
,返回所有数量组合的大小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实现将是完美的。
这是一个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;
}
}
我的想法是每当我们超出我们的条件时,就会在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]
这可能是资源匮乏的问题:但这是我的解决方案
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 ++ ;
}
}
}
}