【问题标题】:Merging sorted arrays, what is the optimum time complexity?合并排序数组,最佳时间复杂度是多少?
【发布时间】:2011-07-04 05:10:27
【问题描述】:

我有 m 个数组,每个数组的长度为 n。每个数组都是排序的。我想创建一个长度为 m*n 的数组,其中包含先前数组的所有值(包括重复值),并已排序。我必须合并这些数组..

我认为最佳时间复杂度是 m*n*log(m)

这是算法的草图..

我创建了一个长度为 m 的支持数组 H,其中包含每个数组第一个元素的所有值。

然后我对这个数组进行排序(m log m),并将最小值移动到输出数组。

然后我用下一个值替换移动的值,从它获取的数组中。实际上我没有替换它,但我将它插入到正确的(排序的)位置。我认为这需要 log m。

我对所有 m*n 值重复此操作...因此 m*n*log m

我的问题..你能想到一个更有效的算法吗?如果 mnlogm 实际上是最优的,你至少能想到一个更简单、更优雅的算法吗?

【问题讨论】:

  • 在有序数组中插入一个元素会花费对数时间吗?

标签: arrays algorithm sorting data-structures complexity-theory


【解决方案1】:

复杂性是对的!但是,您的算法思想有一个小缺陷:您不能在log m 的排序数组中插入项目。您可以在这种复杂性中使用二分搜索找到它的位置,但您可能必须四处移动元素才能将其实际放置在那里。要解决此问题,您可以改用堆数据结构!

多路合并(这是算法的通用名称)通常使用另一种“合并”数据结构实现:锦标赛树。您可以在 Knuth 的“计算机编程艺术”(关于排序的章节,iirc)中找到描述。在这种特定情况下,与堆相比,它在理论上和实践中具有较低的常数因子。

如果您想查看实现,我很确定 GNU C++ 标准库并行扩展中的并行多路合并是通过这种方式实现的。

编辑:我引用了错误的书,现在已修复。

【讨论】:

  • 它们“与最小堆的多路合并”和“与锦标赛树的多路合并”是否具有相同的时间复杂度? (这里,O(m n logm))如果不是,哪一个更有效?谢谢
  • 是的,它们具有相同的渐近时间复杂度,如果这就是您要问的!
【解决方案2】:

你能做的最好是 O(m*n + d)。类似于计数排序:http://en.wikipedia.org/wiki/Counting_sort 如果您知道可能的值范围(例如,d),您可以初始化一个长度为 d 的数组,然后扫描 m 个数组中的每一个,为每个 d 中的每个“bin”添加 1对应于该 bin 的值。然后在新的长度为 m*n 的数组中,为 d 中的每个值添加 bin 的计数。

【讨论】:

  • 正如您所写,这仅在您知道 'd' 并且存在从您的值空间到整数的 easy 映射时才有效。此外,内存复杂度在“d”中是线性的,如果值范围很大,这可能会很糟糕。所以这不一定更好。
  • 是的,我想取决于他的数据集
  • 在应用挂起的 LRU 操作之前,我在 ConcurrentLinkedHashMap 中执行此操作,以便以严格的顺序执行它们。我链上一个冲突,例如封闭寻址。我认为这种方法称为有限高度优先级队列。
猜你喜欢
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
  • 2018-07-23
  • 2012-05-07
  • 2015-01-20
  • 1970-01-01
相关资源
最近更新 更多