我有m个数组,每个数组的长度为n。每个数组都已排序。我想创建一个长度为m * n的单个数组,其中包含前面数组的所有值(包括重复值),已排序。我必须合并这些数组..
我认为最佳时间复杂度是m * n * log(m)
这是算法的草图..
我创建了一个lenth m的支持数组H,其中包含每个数组的第一个元素的所有值。
然后我对这个数组进行排序(m log m),并将min值移动到输出数组。
然后我将移动的值替换为下一个移动的值。实际上我不替换它,但我将其插入右侧(已排序)位置。我想这就是记录。
我对所有m * n值重复这个...因此m * n * log m
我的问题..你能想到一个更有效的算法吗?如果mnlogm实际上是最佳的,你至少可以想到一个更简单,更优雅的算法吗?
答案 0 :(得分:11)
复杂性是对的!但是,您的算法思想存在一个小缺陷:您无法在log m
中的已排序数组中插入项目。你可以在这种复杂性中使用二进制搜索找到它的位置,但是你可能必须移动元素以实际将它放在那里。要解决此问题,您可以使用堆数据结构!
多路合并(这是您的算法的通用名称)通常是通过另一个合并'来实现的。数据结构:锦标赛树。您可以在Knuth"计算机编程艺术"中找到相关描述。 (关于排序的章节,iirc)。与特定情况下的堆相比,它在理论上和实践中具有较低的常数因子。
如果您想查看实现,我非常确定GNU C ++标准库并行扩展中的并行多路合并是以这种方式实现的。
修改:我引用了错误的书籍,现已修复。
答案 1 :(得分:0)
你能做的最好是O(m * n + d)。与计数排序类似:http://en.wikipedia.org/wiki/Counting_sort如果您知道可能的值范围(例如,d),则可以初始化长度为d的数组,然后扫描每个m个数组,在d中为每个“bin”添加1对于与该bin相对应的每个值。然后在d中每个值的新长度为m * n的数组中添加bin所具有的多个计数。