为什么迭代k路合并O(nk ^ 2)?
k路合并是将k个sorting后的数组作为input的algorithm,每个数组的大小为n。 它输出所有元素的单个sorting数组。
它通过使用归并sortingalgorithm中心的“合并”例程将数组1合并到数组2中,然后将数组3合并到这个合并数组中,依此类推,直到所有k数组合并。
我曾经以为这个algorithm是O(kn),因为algorithm遍历每个k个数组(每个长度为n)一次。 为什么是O(nk ^ 2)?
因为它不会遍历每个k个数组。 第一个数组遍历k-1次,第一个作为merge(array-1,array-2),第二个作为merge(merge(array-1,array-2),array-3)…等等。
结果是k-1与n *(k + 1)/ 2的平均大小合并,给出为O(nk ^ 2)的O(n *(k ^ 2-1)/ 2)的复杂度。
你犯的错误是忘记合并是串行的而不是并行的,所以数组并不都是n的大小。
实际上在最坏的情况下,第一个数组会有n个比较,第二个数组会有2n个数据,第三个数据会有3n个数据 ,而第(k-1)n个数据会很快到达。
所以现在复杂性变得简单
n + 2n + 3n + 4n + ... + (k - 1)n = n(1 + 2 + 3 + 4 + ... + (k - 1)) = n((k - 1)*k) / 2 = n(k^2 - k) / 2 = O(nk ^ 2)
🙂
这个怎么样:
步骤1:合并数组(1和2),数组(3和4)等等。 (k / 2arrays合并2n,总工作kn)。
步骤2:合并数组(1,2和3,4),数组(5,6和7,8)等等(4n的k / 4合并,总工作kn)。
第3步:重复…
会有log(k)这样的“steps”,每个都有kn工作。 因此总的工作= O(knlog(k))。
否则,如果我们只是对数组的所有元素进行sorting,我们仍然可以合并O(knlog(kn))的所有时间。
我不同意其他答案。 您不必每次都比较项目1。 您应该简单地将最近的K个项目维护在一个有序集合中。 你删除最小的,并通过它的下一个元素。 这应该是n.log(k)
相关文章 。 免责声明:我参与了写作
k路合并是将k个sorting后的数组作为input的algorithm,每个数组的大小为n。 它输出所有元素的单个sorting数组。
我以为这个algorithm是O(kn)
我们可以通过矛盾来反驳。 为m个项目定义一个sortingalgorithm,使用k = m和n = 1的algorithm。 通过假设,sortingalgorithm在O(m)时间成功。 矛盾的是,已知任何sortingalgorithm的最坏情况至less是O(m log m)。
一个通用的实现为每个k个sorting的数组{i_1,i_2,i__k}保留一个索引数组。 在每次迭代中,algorithm从所有k个数组中find最小的下一个元素,并将其存储在输出数组中。 由于您正在进行kn迭代和每次迭代扫描k个数组,因此总的复杂度为O(k ^ 2 * n)。
这是一些伪代码:
Input: A[j] j = 1..k : k sorted arrays each of length n Output: B : Sorted array of length kn // Initialize array of indexes I[j] = 0 for j = 1..k q = 0 while (q < kn): p = argmin({A[j][I[j]]}) j = 1..k // Get the array for which the next unprocessed element is minimal (ignores arrays for which I[j] > n) B[q] = A[p][I[p]] I[p] = I[p] + 1 q = q + 1
1)你有k个sorting的数组,每个数组的大小为n。 因此元素总数= k * n
2)取所有K个数组的第一个元素并创build一个序列。 然后find这个序列的最小值。 这个最小值被存储在输出数组中。 findk个元素的最小值的比较次数是k-1。
3)因此,比较的总数
=(比较/元素)*元素的数量
=(k-1)* k * n
= k ^ 2 * n //近似
-
你有k个数组,每个数组都有n个元素。 这意味着总共k * n个元素。
-
考虑一下k * n的matrix。 要将第一个元素添加到合并/最终数组中,您需要比较k个数组的头部。 这意味着最后一个数组中的一个元素需要进行k次比较。
所以从1和2中,对于K n个元素,总的时间是O(k k * n)。