我正在寻找一种算法,该算法可以打印M个自然数的所有组合,这些组合可以重复创建给定的数字(N)。
让我们说我们的java函数是:public static String [] foo(6,3)其中6是N,3是M.
答案应该是:
0,0,6
0,1,5
0,2,4
0,3,3
1,1,4
1,2,3
2,2,2
and foo(7,4):
0,0,0,7
0,0,1,6
0,0,2,5
0,0,3,4
0,1,1,5
0,1,2,4
0,1,3,3
1,1,1,4
1,1,2,3
1,2,2,2 (if im not wrong...)
提前谢谢!
答案 0 :(得分:1)
这是一种递归方法,观察你开始需要M个数字,这可以分解成一个更简单的M-1数问题,直到M = 1.
public class RecursiveCombinations {
public static void main(String[] args) {
solve(4,7,0,"");
}
private static void solve(int M, int remainingValue, int previousLevel, String solutionSoFar) {
if (M == 1) {
System.out.println(solutionSoFar+remainingValue);
return;
}
for (int i = previousLevel; i<=remainingValue/M; i++) {
String s = solutionSoFar+i+",";
solve(M-1, remainingValue-i, i, s);
}
}
创建输出:
0,0,0,7
0,0,1,6
0,0,2,5
0,0,3,4
0,1,1,5
0,1,2,4
0,1,3,3
0,2,2,3
1,1,1,4
1,1,2,3
1,2,2,2
答案 1 :(得分:0)
最简单的方法是生成长度为M的数组以及最多N个数字的所有可能组合,并测试每一个数字以获得正确的结果。
非常蛮力,但会工作。你可以从那里建立起来(消除加倍的结果......)
您可能还想查看Backtracking
这可能是这样的:
import java.util.LinkedList;
public class Tests
{
public static void main(String[] aargh)
{
LinkedList<int[]> arr = numarrays(7,4);
for(int i = 0; i< arr.size();i++)
{
int[] curr = arr.get(i);
for(int j = 0; j < curr.length;j++)
{
System.out.print(curr[j]+" ,");
}
System.out.println();
}
}
public static LinkedList<int[]> numarrays(int result, int depth)
{
LinkedList<int[]> retVal = new LinkedList<int[]>();
int[][] val = new int[1][];
while(next(result,depth,val))
{
if(reject(result, val[0])) continue;
if(!accept(result, val[0])) continue;
retVal.add(val[0].clone());
}
return retVal;
}
private static boolean reject(int max, int[] in)
{
int sum = 0;
for(int i = 0; i< in.length; i++)
{
sum += in[i];
if(sum > max) return true;
}
return false;
}
private static boolean accept(int target, int[] in)
{
int sum = 0;
for(int i = 0; i< in.length; i++)
{
sum += in[i];
}
if(sum == target) return true;
return false;
}
private static boolean next(int max, int depth, int[][] val)
{
if(val[0] == null)
{
val[0] = new int[depth];
return true;
}
return nextrec(max,val[0],0);
}
private static boolean nextrec(int max, int[] curr, int i)
{
if(i>=curr.length) return false;
if(nextrec(curr[i],curr,i+1)) return true;
if(curr[i]< max)
{
curr[i]++;
zerorec(curr,i+1);
return true;
}
return false;
}
private static void zerorec(int[] curr, int i)
{
if(i>=curr.length) return ;
curr[i] = 0;
zerorec(curr,i+1);
}
}