我正在寻找一种算法,用于在非常特定的条件下交叉两个小的未排序数组。
蛮力/排序和交叉解决方案都不是那么糟糕,但我不认为它们足够快。有更优化的解决方案吗?
答案 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个项目。