检测数字对中重叠的最快方法

时间:2013-05-07 14:48:39

标签: java algorithm

我们有两对数字。第一对由a1, a2和第二对组成 由b1, b2组成。我们希望确定a中的任何元素是否在b中,反之亦然。 这很简单:

int a1, a2, b1, b2;

// is it possible to do better than this:

boolean hasOverlap = a1 == b1 || a1 == b2 || a2 == b1 || a2 == b2;

问题是,理论上可以更快地做到这一点吗?或许通过 一些聪明的使用逐位算术?

编辑清晰度:对于特异性,想象一下我们正在尝试优化java程序。

奖金问题

假设我们有任意数量的对,而不是只有两对。您 可以想象一个由100个长度为2的数组组成的阵列。效率最高的是什么 如果该对包含显示的元素,则从该列表中删除任何对 列表中的另一对?

例如:[[1,2], [3,4], [2,5]]将缩减为[[3,4]]

3 个答案:

答案 0 :(得分:0)

第一个问题从算法的角度来看是荒谬的,因为每个解决方案都具有相同的复杂性(即O(1))。

对于奖金问题,这相当于在列表中查找重复项的问题(如果数字出现两次,只检查它是否出现在不同的对中)并且可以在O(n * Log(n))中完成通过对列表进行排序,然后使用先前看到过的数字的哈希集扫描它等于或等于O(n)的连续数字。

答案 1 :(得分:0)

请参阅以下答案,了解为什么Java中的逐位操作可以比逻辑操作更快:https://stackoverflow.com/a/11052460/758446

因此,让我们将原始逻辑运算转换为按位运算:

boolean hasOverlap = a1 == b1 || a1 == b2 || a2 == b1 || a2 == b2;

boolean hasOverlap = !(a1 ^ b1) | !(a1 ^ b2) | !(a2 ^ b1) | !(a2 ^ b2);

请注意,这是混合C和Java样式的逐位操作,不会完全用Java编译。如果有人有进行此编译的提示,请发表评论。自从我在Java中进行了一些操作以来已经有一段时间了。

答案 2 :(得分:0)

与@BlackVegetable的工作方式类似,但是执行显式比较为0,因为java不会为我们进行转换:

boolean hasOverlap = ((a1 ^ b1) == 0) | ((a1 ^ b2) == 0) | ((a2 ^ b1) == 0) | ((a2 ^ b2) == 0);

在这里,我认为只有在你有充分理由使用它的情况下才应该使用按位或|。你错过了短路,与其他任何收益相比,这似乎很可能对性能产生更大的影响,相比之下:

boolean hasOverlap = ((a1 ^ b1) == 0) || ((a1 ^ b2) == 0) || ((a2 ^ b1) == 0) || ((a2 ^ b2) == 0);

由于通常比较0更有效,因此可能会有效率增益。不过,我对此表示怀疑,因为我确信设计JVM的人会认为他们可以将int == int实现为int ^ int == 0


这个对我来说似乎更有趣:

boolean hasOverlapmul = ((a1 ^ b1) * (a1 ^ b2) * (a2 ^ b1) * (a2 ^ b2))==0;