k-way merge是一种算法,它采用大小为n的输入k排序数组。它输出所有元素的单个排序数组。
它通过使用合并排序算法中心的“合并”例程将数组1合并到数组2,然后将数组3合并到此合并数组,依此类推,直到所有k个数组合并为止。
我原以为这个算法是O(kn)因为算法遍历每个k个数组(每个长度为n)一次。为什么是O(nk ^ 2)?
答案 0 :(得分:60)
因为它不会遍历每个k数组一次。第一个数组遍历k-1次,第一个数组为merge(array-1,array-2),第二个数组为merge(merge(array-1,array-2),array-3)...依此类推
结果是k-1与平均大小n *(k + 1)/ 2合并,给出O(n *(k ^ 2-1)/ 2)的复杂度,即O(nk ^ 2)
你犯的错误是忘记了合并是串行完成而不是并行完成,所以数组的大小都不是n。
答案 1 :(得分:39)
实际上在最糟糕的情况下,第一个阵列将进行 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)
: - )
答案 2 :(得分:15)
这个怎么样:
第1步: 合并数组(1和2),数组(3和4)等。 (k / 2阵列合并2n,总工作量)。
第2步: 合并数组(1,2和3,4),数组(5,6和7,8)等等(k / 4合并4n,总工作量)。
第3步: 重复...
会有log(k)这样的“Steps”,每个都有kn工作。因此,完成的工作总数= O(k.n.log(k))。
即便如此,如果我们只是对数组的所有元素进行排序,我们仍然可以在O(k.n.log(k.n))时间内合并所有元素。
答案 3 :(得分:6)
我不同意其他答案。您不必每次比较1到1的项目。 您应该只是在排序集中维护最新的K项。 您删除最小的并通过其下一个元素重新发送它。这应该是n.log(k)
相关article。免责声明:我参与了写作
答案 4 :(得分:6)
k-way merge是一种算法,它采用大小为n的输入k排序数组。它输出所有元素的单个排序数组。
我原以为这个算法是O(kn)
我们可以通过矛盾反驳这一点。为使用您的算法的m个项目定义排序算法,其中k = m且n = 1。根据该假设,排序算法在O(m)时间内成功。矛盾,众所周知,任何排序算法的最坏情况至少为O(m log m)。
答案 5 :(得分:3)
一个常见的实现为k个排序的数组{i_1,i_2,i__k}中的每一个保留一个索引数组。在每次迭代时,算法从所有k个数组中找到最小的下一个元素并将其存储在输出数组中。由于您每次迭代都在进行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
答案 6 :(得分:3)
1)你有k个排序的数组,每个数组大小为n。因此,元素总数= k * n
2)获取所有k个数组的第一个元素并创建一个序列。然后找到这个序列的最小值。此最小值存储在输出数组中。找到k个元素的最小值的比较次数是k-1。
3)因此比较总数
=(比较/元素)*元素数量
=(k - 1)* k * n
= k ^ 2 * n //大约是
答案 7 :(得分:0)
你有k个数组,每个数组都有n个元素。这意味着总共k * n个元素。
将其视为k * n的矩阵。要将第一个元素添加到merged / final数组,需要比较k个数组的头部。这意味着对于最终数组中的一个元素,您需要进行k次比较。
因此,从1和2开始,对于K n个元素,所用的总时间为O(k k * n)。
答案 8 :(得分:0)
对于那些想了解详细信息或需要帮助的人,我将扩展Recurse的answer和后续评论
k-1
合并,因为最后一个数组未与任何内容合并Sn=n(a1 + an)2
逐步完成k
数组与n
元素的前4次合并
+-------+-------------------+-------------+
| Merge | Size of new array | Note |
+-------+-------------------+-------------+
| 1 | n+n = 2n | first merge |
| 2 | 2n+n = 3n | |
| 3 | 3n+n = 4n | |
| 4 | 4n+n = 5n | |
| k-1 | (k-1)n+n = kn | last merge |
+-------+-------------------+-------------+
要找到平均大小,我们需要将所有大小相加并除以合并数(k-1
)。使用公式将前n
个词Sn=n(a1 + an)2
相加,我们只需要 first 和 last 个词:
2n
(第一学期)kn
(上学期)我们要对所有术语求和,所以n=k-1
(我们拥有的术语数)。插入数字,我们得到所有项之和的公式
Sn = ( (k-1)(2n+kn) )/2
但是,要找到平均大小,我们必须除以项数(k-1
)。这样就消除了分子中的k-1
,剩下的平均大小为
(2n + kn)/2
现在我们有了平均大小,我们可以将其乘以合并次数,即k-1
。为了使乘法更容易,请忽略/2
,而只需乘分子:
(k-1)(2n+kn)
= (k^2)n + kn - 2n
在这一点上,您可以重新引入/2
,但是没有必要,因为很明显,主导术语是(k^2)*n