假设我有N个未整数的整数数组。我想找到这些数组的交集。
有两种方法可以解决这个问题。
一,我可以使用nlogn排序对数组进行排序,例如QuickSort或MergeSort。然后我可以在每个数组的开头放一个指针。将每个数组与它下面的数组进行比较,迭代任何数组[指针]较小的指针,或者如果它们都相等,你就找到了一个交集。
这是一个O(nlogn)解决方案,具有恒定的内存(因为所有内容都是就地完成的)。
第二个解决方案是使用哈希映射,将第一个数组中出现的值作为键放入,然后在遍历其余数组时递增这些值(然后抓取值为N的所有值) 。这是一个O(n)解决方案,带有O(n)内存,其中n是所有数组的总大小。
理论上,前一种解决方案是o(nlogn),后者是O(n)。但是,哈希映射没有很好的局部性,因为由于冲突,项目可以随机分散在地图中。另一个解决方案,虽然o(nlogn),一次遍历一个阵列,表现出优秀的局部性。由于CPU倾向于将数组值从当前索引旁边的内存中提取到缓存中,因此O(nlogn)解决方案将比哈希映射解决方案更频繁地访问缓存。
因此,给定一个非常大的数组大小(随着元素数量变为无穷大),o(nlogn)解决方案实际上是否比O(n)解更快?
答案 0 :(得分:1)
对于整数,您可以使用非比较排序(请参阅counting, radix sort)。可以编码大的集合,例如,顺序运行到范围。这将压缩数据集并允许跳过大块(参见RoaringBitmaps)。有可能是硬件友好的并且具有O(n)复杂性。
复杂性理论不考虑常数。正如您所怀疑的那样,由于隐藏的常量,总是有可能使复杂度更高的算法比替代算法更快。通过利用问题的性质,例如,将解决方案限制为整数,有一些潜在的优化不适用于通用方法。良好的算法设计通常需要理解并利用这些约束。