查找满足某些条件的数组的子集

时间:2019-11-29 15:30:25

标签: javascript algorithm

假设给定一个由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;
}

2 个答案:

答案 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的代码。

NODE_EXTRA_CA_CERTS=fullpath_to_certificates_file

如您所见,此代码需要N *(N-1)/ 2循环,并且没有内存。即使对于非常大的N,找到n和m也要花费几毫秒的时间。 在我的计算机(Core i5 4460 @ 2.90GHz)上找到N = 10000000的解决方案大约需要20到80毫秒。

相关问题