交叉算法为两个未排序的小数组

时间:2013-02-05 07:23:37

标签: arrays algorithm set intersection

我正在寻找一种算法,用于在非常特定的条件下交叉两个小的未排序数组。

  • 数组项的类型只是整数或整数类型。
  • 大量时间(约30~40%?),一个或两个数组可能为空。
  • 阵列通常非常小 - 通常是1~3个项目,我预计不会超过10个。
  • 将非常频繁地调用交叉函数。
  • 我不关心平台相关的解决方案 - 我正在研究x86 / windows / C ++

蛮力/排序和交叉解决方案都不是那么糟糕,但我不认为它们足够快。有更优化的解决方案吗?

4 个答案:

答案 0 :(得分:3)

由于数组是原始类型,并且足够短以便在高速缓存行中,快速实现将集中在比较的战术机制而不是大的O复杂性,例如避免使用散列表,因为这些散列表通常涉及散列和间接,并且总是会涉及大量的管理开销。

如果您有两个已排序的数组,则交点为O(n + m)。你说排序然后交叉是'蛮力',但你不能更快地做到。

如果数组存储已排序,当然,如果您说您经常调用交叉点,则会进一步获得。

交叉点本身可以​​是done with SSE

答案 1 :(得分:2)

这是一个潜在的优化:检查两个数组是否都有最大元素< = 32(或64,或甚至16)。如果是,则填充该大小的两个位图(类型为uint32_t等)并使用二进制AND &进行交叉。如果他们不是,那就采取分类。

或者,使用highly efficient integer set representation而不是排序,因为Briggs和Torczon允许线性时间与O( m + n )结构相交。 (min( m n ))相交。这应该比具有比排序更好的边界的哈希表快得多。

答案 2 :(得分:1)

为了确定两个集合的交集,您必须至少检查一次所有元素,这意味着最优的解决方案类产生O(n + m),其中n是一个集合中的元素数量和m另一个元素的数量。

您可以使用哈希表来实现这一点。鉴于您的项目是整数类型,您可以指望找到快速哈希函数。一个简单的算法是:

  • 迭代第一组并将所有元素添加到哈希表
  • 迭代第二组并为每个元素检查它是否存在于哈希表中,如果存在,则将其添加到交集中或只打印它。

假设你的哈希和你的哈希查找是O(1),这将是O(n + m)。

鉴于您知道这些集合经常是空的,您可以通过首先检查其中一个集合是否为空来优化它,如果是,则返回一个空集。那当然假设你先知道计数并且可以在不迭代集合的情况下计算它。如果恰好是这种情况,您可以通过始终首先读取和散列较小的集合来进一步优化,确保您的散列表内存使用量将是两者中较小的一个。

答案 3 :(得分:1)

好吧,由于你的数组非常小,使用插入排序将是对这两个数组进行排序的最快方法,C ++ STL也对小于16个项目的数组使用插入排序。然后,您可以在这两个数组上使用迭代器来比较和交叉数组。

可能还有其他算法可以更快地执行,但是这些算法的开销可能太大,每个阵列有3-4个项目。