所以我在想这个问题的算法:
想象一下,我们有以下数组
a = {1, 2, 4, 5, 7}
并希望从这些数字中得到所有可能的总和,这些数字等于给定的数字N
(目前,求和的顺序并不重要)。
如果N=8
有几个有效答案:
1 + 2 + 5
1 + 7
2 + 2 + 2 + 2 ...
所以现在我会向你解释我的方法。
首先,我们创建一个长度为b
的新数组N+1
,并将数组x
中的每个数字a
放到索引处的数组b
[N-x]
并用-1填充其余元素。
这应该创建以下数组:
b = {-1, 7, -1, 5, 4, -1, 2, 1, -1}
正如您所看到的,b的每个元素都不是-1,需要添加到其索引中以获取N
。 (示例:b[1]=7
=>索引= 1,值= 7 => 7 + 1 = 8 = N
)
我们现在做的是,我们遍历此数组x
的每个索引b[x]!=-1
并从头开始整个过程,但这次我们说N=x
以便我们得到获取索引x
的所有可能总和(如上所示)是我们需要添加到b[x]
元素值的值。
我们以递归的方式完成所有这些操作,一旦到达索引等于0的点,我们就会打印整个连接链。
我用Java实现了它,它工作正常:
public static void main(String[] args) {
int[]numbers = {1, 2, 4, 5, 7};
int n = 8;
numbers = summandArray(numbers, n);
printArray(numbers);
getSums(numbers, n, "");
}
public static void getSums(int[] numbers, int n, String summands) {
String startSummands = summands;
for(int i = 0; i < numbers.length; i++) {
summands = startSummands;
if(numbers[i] != -1) {
int neededSummand = i;
if(neededSummand == 0) {
summands+=numbers[i];
System.out.println(summands);
}
else {
int[] newNumbers = summandArray(numbers, neededSummand);
summands+=numbers[i]+"+";
getSums(newNumbers, neededSummand, summands);
}
}
}
}
public static int[] summandArray(int[] array, int n) {
int[] result = new int[n+1];
for(int i = 0; i < result.length; i++) {
result[i] = -1;
}
for(int i = 0; i < array.length; i++) {
if(array[i] <= n && array[i] != -1) {
int index = n-array[i];
result[index] = array[i];
}
}
return result;
}
但是我不太确定算法的执行情况。我的意思是,这不是一个非常复杂的蛮力版本,因此效率非常低吗?
感谢您抽出宝贵时间:)
答案 0 :(得分:0)
您要做的是获取数组的排列。使用每个排列,您可以根据需要对值进行总计。还有另一个StackExchange托管站点允许完成代码审查。您可能希望与其他算法进行比较:
答案 1 :(得分:0)
你的方法就像子集和问题的有效动态编程算法一样(你的任务就是这个问题),但似乎它没有重用计算数据。请注意,使用DP计算可能变量的数量需要伪多项式时间O(N * Sum),而所有变量的输出都呈指数增长。
您可以将已计算的子任务存储在其他数组/列表中 - 这是memoization
(从上到下)的方法,很容易修改递归以利用它。
另一种DP方法 - 自下而上填表:
Make array Sol[n+1] of lists of lists
For every input item X:
Scan Sol array from the last to the first index i
if (i==X) or (Sol[i-X] is not empty):
Add all Sol[i-X][j]+X to Sol[X] list
example for [1,2,3,5] array after outer loops:
[] [1] []...
[] [[1]] [[2]] [[1,2]]...
[] [[1]] [[2]] [[1,2],[3]] [[1,3]] [[2,3]] [[1,2,3]]
[] [[1]] [[2]] [[1,2],[3]] [[1,3]] [[2,3],[5]] [[1,2,3],[1,5]]
[[2,5]] [[1,2,5],[3,5]] [[1,3,5]] [[2,3,5]] [[1,2,3,5]]