在 JavaScript 中将数组中所有成对的数字相加

4
我有一个像这样的数组: [20,40,60,60,20] 要求是:对于任意两个数进行求和,如果结果可以被60整除,则计数1。因此,这个数组应该返回3对数字(20,40),(40,20),(60,60)。
这是我写的代码,但它给了我4而不是3。
function countPlayList (array) {
  let count = 0;
  for (let i = 0; i < array.length-1; i++) {
    for (let j = 0; j < array.length-1; j++) {
      let a = array[i];
      let b = array[j];
      if (checkPlayTime(a, b) && notDuplicate(i, j)) {
        count++;
      }
    }
  }
  return count;
}

function checkPlayTime (a, b) {
  return Number.isInteger((a + b)/60);
}

function notDuplicate (x, y) {
  return x !== y ? true : false;
}

我这里有什么遗漏吗?


1
为什么 notDuplicate() 函数中 [30, 30] 的返回值是1,还是不是?这可能与您的 for 循环中的条件有关。您可能需要考虑在每个循环中需要检查哪些元素。 - Andreas
你指定的三组数据不正确 - 实际上应该是 (20, 40), (40, 20) 和 (40, 20),而不是 (60, 60),因为当调用 notDuplicate 时,它会返回 false。 - half of a glazier
1
只是一个注释:这可以在O(n)的平均时间内完成。模60,加法逆元很明显,所以只需要计数:arr.map(e => e % 60).reduce((p, c) => { p.n += p[(60 - c) % 60] || 0; p[c] = (p[c] || 0) + 1; return p; }, { n: 0 }).n - ASDFGerte
3个回答

1

你的代码有两个问题

  1. 你没有在整个数组上运行,你需要运行 (let i = 0; i < array.length; i++) 或者 (let i = 0; i <= array.length - 1; i++)
  2. 内部循环需要从外部索引+1开始,这样你就不会检查每个组合两次。

function countPlayList (array) {
  let count = 0;
  for (let i = 0; i < array.length - 1; i++) {
    for (let j = i + 1; j < array.length; j++) {
      let a = array[i];
      let b = array[j];
      if (checkPlayTime(a, b)) {
        count++;
      }
    }
  }
  return count;
}

function checkPlayTime (a, b) {
  return Number.isInteger((a + b)/60);
}

console.log(countPlayList([20,40,60,60,20]));

顺便说一句,没有必要使用return x !== y ? true : false;,你可以直接使用return x !== y;,因为这个值已经是布尔型的了。


1
外部必须检查到倒数第二项。 - Nina Scholz

1

Start the second loop from i+1 since you have taken the ith index already in the first loop then you have to traverse from i+1 to length of the array, also run the both loop till i < array.length since you are starting from index 0

function countPlayList (array) {
  let count = 0;
  for (let i = 0; i < array.length; i++) {
    for (let j = i+1; j < array.length; j++) {
      let a = array[i];
      let b = array[j];
      if (checkPlayTime(a, b) && notDuplicate(i, j)) {
        count++;
      }
    }
  }
  return count;
}

function checkPlayTime (a, b) {
  return Number.isInteger((a + b)/60);
}

function notDuplicate (x, y) {
  return x !== y ? true : false;
}
console.log(countPlayList([20,40,60,60,20]))


"运行两个循环,直到 i < array.length" - 这部分是不必要的。 - Andreas
@Andreas 我认为这是必要的,第一个循环覆盖了从 i = 0arraylength - 1 的范围,第二个循环从 j = i+1arraylength - 1,否则中间节点将会丢失,对吧? - Nitheesh
你为什么想要检查 array[array.length - 1] + array[array.length - 1] - Andreas

1
你可以更改一些部分:
  • i + 1迭代内部,直到小于数组的length,
  • 使用实际对的字符串值,
  • 使用Set来跟踪已看到的对,
  • 使用不同的检查求和并使用余数运算符获取剩余部分,
  • 使用已看到的值进行检查,
  • 存储未见过的对,
  • 返回pairssize作为计数。

function countPlayList(array) {
    let pairs = new Set;
        
    for (let i = 0; i < array.length - 1; i++) {
        for (let j = i + 1; j < array.length; j++) {
            let a = array[i],
                b = array[j],
                pair = [a, b].join('|');
                
            if ((a + b) % 60 === 0 && !pairs.has(pair)) {
                pairs.add(pair);
            }
        }
    }
    console.log(...pairs);
    return pairs.size;
}

console.log(countPlayList([20, 40, 60, 60, 20]));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接