假设给定一个由N个数字组成的数组。
如何找到其和是N的倍数的子集?
我想知道最好的方法。
递归函数将是正确的选择,但是不允许大量N的堆栈溢出。
这是我的代码,但是不起作用。
const arr = [];
const TOTAL_NUM = 5;
let sum = 0;
for (let i = 0; i < TOTAL_NUM; i++) {
arr.push(parseInt(Math.random() * TOTAL_NUM) + 1);
sum += arr[i];
}
const mod = sum % TOTAL_NUM;
for (let i = 0; i < TOTAL_NUM; i++) {
let sum = arr[i]
let found = false;
for (let j = i + 1; j < TOTAL_NUM; j++) {
sum += arr[j];
if (sum % TOTAL_NUM === 0 || (sum - mod) % TOTAL_NUM === 0) {
found = true;
console.log('Sum = %d', sum);
break;
}
}
if (found) break;
}
答案 0 :(得分:0)
我们不一定需要递归。到目前为止,我们可以迭代已知的余数。
下面的JavaScript代码(这是详尽无遗的;我们可以有一个空间效率更高的版本,通过调整存储的内容仅返回一个子集):
// 'rem' stands for "remainder"
function f(A){
let N = A.length
let rems = {0: [[]]}
for (let a of A){
let newRems = {}
for (let rem in rems){
let newRem = (a + Number(rem)) % N
newRems[newRem] = (rems[newRem] || []).concat(
rems[rem].map(x => x.concat(a)))
}
newRems[a % N] = (rems[a % N] || []).concat([[a]])
rems = Object.assign(rems, newRems)
}
return rems[0].slice(1)
}
var A = [1, 6, 2, 3, 4]
console.log(JSON.stringify(A))
console.log(`N: ${A.length}`)
console.log(JSON.stringify(f(A)))
答案 1 :(得分:0)
我想回答我的问题并得到观众的评价。 这是我当前的代码。我会解释。
假设我们有N个数字组成的数组。
在变量i = 0的循环中,我们获得N个子集及其内部和。如果至少有一个子集的和是N的倍数,那将是一个解决方案。如果不是,(sum%N)的值将取1到(N-1)之间的一个值。存在N个和和(N-1)个可能的余数。因此,存在至少一对(n,m),第n个和第m个和具有相同的余数,其中0 下面是查找n和m的代码。 如您所见,此代码需要N *(N-1)/ 2循环,并且没有内存。即使对于非常大的N,找到n和m也要花费几毫秒的时间。
在我的计算机(Core i5 4460 @ 2.90GHz)上找到N = 10000000的解决方案大约需要20到80毫秒。 NODE_EXTRA_CA_CERTS=fullpath_to_certificates_file