问题在标题中。
例如:
鉴于此array = [1,1,2,2,3,7,9,1]
和sum = 7
,我希望得到以下结果:
1,1,2,2,1
1,1,2,3
...
7
一个二次时间的答案是微不足道的,我正在寻找一个次二次时间的解决方案...
我目前的解决方案:
function subsetSum(numbers, target, partial) {
var s, n, remaining;
partial = partial || [];
// sum partial
s = partial.reduce(function (a, b) {
return a + b;
}, 0);
// check if the partial sum is equals to target
if (s === target) {
console.log(partial.join(","))
}
if (s >= target) {
return; // if we reach the number we don't bother to continue
}
for (var i = 0; i < numbers.length; i++) {
n = numbers[i];
remaining = numbers.slice(i + 1);
subsetSum(remaining, target, partial.concat([n]));
}
}
subsetSum([1,1,2,2,3,7,9,1], 7);
输出:
1,1,2,2,1
1,1,2,3
1,1,2,3
1,2,3,1
1,2,3,1
1,2,3,1
1,2,3,1
2,2,3
7
对于2k个1位数的数字,在处理4分钟后,我的盒子中的nodejs(v11.14.0)吐出了:
致命错误:接近堆限制的无效标记紧凑分配失败-JavaScript堆内存不足
:-(
答案 0 :(得分:4)
您可以通过避免使用内置的数组方法(迭代和最昂贵的切片)进行递归调用,并采用递归函数,该函数获取要获取的下一个数字的索引,收集的值的数组和新的目标,而无需最后一次获取的值。
此方法返回所有可能的值,这些值不是唯一的,取决于给定的数据。这种方法仅适用于正数。
function subsetSum(numbers, target) {
function iter(index, right, delta) {
if (!delta) return result.push(right);
if (index >= numbers.length) return;
if (delta - numbers[index] >= 0)
iter(index + 1, [...right, numbers[index]], delta - numbers[index]);
iter(index + 1, right, delta);
}
var result = [];
iter(0, [], target);
return result;
}
subsetSum([1, 1, 2, 2, 3, 7, 9, 1], 7).map(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }