你有一个数组有一组正数和负数,打印所有子集和等于0。
我可以想到这样的方法,我可以凸轮制作givcen阵列的所有功能,并检查它们的总和是否为0.不会像优化解决方案那样llok 我
看完之后在网上看起来有点类似的问题,看起来它可以通过动态编程解决,如下面的程序来查找是否存在组合 总结11只是一个例子?
public boolean subsetSum(int input[], int total) {
boolean T[][] = new boolean[input.length + 1][total + 1];
for (int i = 0; i <= input.length; i++) {
T[i][0] = true;
}
for (int i = 1; i <= input.length; i++) {
for (int j = 1; j <= total; j++) {
if (j - input[i - 1] >= 0) {
T[i][j] = T[i - 1][j] || T[i - 1][j - input[i - 1]];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[input.length][total];
}
public static void main(String args[]) {
TestDynamic ss = new TestDynamic();
int arr1[] = {2, 3, 7, 8};
System.out.print(ss.subsetSum(arr1, 11));
}
但我不知道如何将上述程序扩展到
1)包括负数
2)找到元素的组合,使得和为零(上面的程序只是发现它是否可以得到总和而不是
找到哪一组数字使其为零)
答案 0 :(得分:1)
这是Javascript中的完整实现。您可以使用node.js运行它。
function target_sum(a, k, x)
{
if (k == a.length) return [];
if (a[k] == x) {
return [[a[k]]];
} else {
var s = target_sum(a, k + 1, x); // not using a[k]
var t = target_sum(a, k + 1, x - a[k]); // using a[k]
for (var i = 0; i < t.length; ++i) {
t[i].unshift(a[k]); // a[k] is part of the solution
s.push(t[i]); // merge t[] into s[]
}
return s;
}
}
var s = target_sum([1,4,5,2,7,8,-3,-5,-6,9,3,-7,-1,5,6], 0, 0);
for (var i = 0; i < s.length; ++i)
console.log(s[i].join(","));
请注意,这是一种指数算法。不要在大型阵列上使用它。
Erwin Rooijakkers也指出了正确的方向。特别是,this post给出了另一种算法。我可能错了以下 - 我相信算法会为空间换取速度。它避免了将数组转移到调用堆栈中,但它必须做更多的递归来实现它。
编辑:关于你提到的算法。它不是指数级的,但如果我是对的,它只适用于正数。它的时间复杂度也与目标总和成正比,根据输入情况,这可能并不理想。