检查N> 2个数组之间的相等性是否具有最佳性能?

时间:2018-10-02 21:23:36

标签: javascript arrays equality

我想检查n数组是否在JavaScript中都包含相同的整数?最有效的方法是什么?

2 个答案:

答案 0 :(得分:1)

如果数组中只有数字-使用基本CRC算法的某些变体-每个数组的复杂度为O(n),所以它可能是最快的https://en.wikipedia.org/wiki/Cyclic_redundancy_check

类似的想法,计算总和(数组)和乘积(数组),您可以使用O(n)计算两个值。例如:

   1, 5, 6, 7 ,8      sum=27, prod=1680
   7, 8, 1, 5, 6      sum=27, prod=1680

但是

   3, 8, 5, 5, 6      sum=27, prod=3600

注意的特殊情况是0!由于那会使产品无效,因此所有值都应+1使用。

NOTE2 请记住,CRC算法的思想是使用一个字节或dword变量作为总数,并且该变量最终会溢出。

例如对于字节:250 + 10 = 5,因为该字节在255处溢出。但是这是可以的,因为两个数组都会溢出,并且错误报告的可能性很小。我相信,只要我们努力尝试,就可以从数学上证明这是可以的。

但是,如果您懒于进行数学运算并且需要绝对确定性,则可以使用此方法快速筛选所有否定候选对象,然后仅对正候选对象进行排序和比较。仍然比仅使用sort + compare更快。

注意3: 只是意识到您使用的是JS,而JS的数字有点乱,实际上并不会因算术运算而溢出。

但是,它的确会因逻辑运算符而溢出,并且CRC算法确实使用了xor,因此效果很好。这是CRC算法: https://en.wikipedia.org/wiki/Cyclic_redundancy_check

这是一些开源实现:https://github.com/emn178/js-crc/blob/master/src/crc.js 在表面上,vista似乎遵循该算法,但是我不确定它的质量如何,您的尽职调查也是如此!

答案 1 :(得分:1)

此解决方案避免使用sort,将算法设为O(n²),其中n是数组的数目和长度。它具有不更改数组的附加好处,并且让我们传递包含任何类型的数组,而不仅仅是数字。它通过为每个阵列项目计算一个频率袋,然后评估它们是否都保存相同的数据来进行操作。 toBagbagsEqual函数均为O(n)。这使得主要算法为arraysSame O(n²)。使用sort代替频率袋会使解决方案O(n²log(n))变得差强人意。

function arraysSame(...arrays) {
  if(arrays.length < 2) return true;

  let bag1 = toBag(arrays[0]);
  for(let i = 1; i < arrays.length; i++) {
    const bag2 = toBag(arrays[i]);
    if(!bagsEqual(bag1, bag2)) return false;
  }

  return true;
}

function bagsEqual(bag1, bag2) {
  if(bag1.size != bag2.size) return false;

  for(const [key, value] of bag1) {
    if(!bag2.has(key)) return false;
    if(value != bag2.get(key)) return false;
  }

  return true;
}

function toBag(array) {
  const bag = new Map();

  for(const val of array) {
    const count = bag.get(val) || 0;
    bag.set(val, count + 1);
  }

  return bag;
}