这是CLRS的2-1.b问题。 我不明白如何在n * lg(n / k)中合并大小为k的n / k数组。 我能想到的最好的解决方案是通过在每个子列表的min元素中搜索min元素来填充大小为n的最终数组的每个条目。这导致O(nk)。在指定时间内执行此操作的算法是什么?
答案 0 :(得分:0)
我刚刚提出这个问题,我认为答案如下: 子列表仍然一次合并两个。 1)考虑合并每个“级别”需要多长时间。 2)考虑有多少合并操作(你开始的第一个列表下面的'级别'的数量)。
合并每个级别多长时间? 每个子列表都有k个元素,因此有(n / k)个子列表。因此,元素总数为k *(n / k)= n,因此每个级别的合并操作为theta(n)。
有多少合并操作(级别)?
If there is 1 sorted sublist: 0
If there are 2 sorted sublists: 1
If there are 4 sorted sublists: 2
If there are 8 sorted sublists: 3
If there are 16 sorted sublists: 4
1 = 2^0
2 = 2^1
4 = 2^2
8 = 2^3
16 = 2^4
因此,我们可以制定一般规则,格式与上面列出的具体规则相同:
If there are 2^p sorted sublists: p
当我们需要问"2 to the power 'what?' = m"
时,我们需要一个对数。
所以,如果我们问"2 to the power 'what?' = 16?"
答案是log to base 2 of 16 = lg 16 = 4
因此,询问有多少级别的合并操作与询问“2权力”是什么一样? = m“。
我们现在知道答案是log to base 2 of n = lg m
。
因此,我们现在知道合并操作有lg m
个级别,每个级别的合并操作需要n
次。因此总时间为n * lg m = n lg m
请记住,m是我们要合并的数字元素,在这种情况下,是算法的插入排序部分返回的已排序子列表的数量。这是n/k
。因此,总时间为n log (n/k)
。
答案 1 :(得分:0)
`我们总共有n个元素,即大小为k的n / k个列表(假设有链表)。 令m = n / k。
1。取一个大小为m的数组。用这些n / k列表的第一个元素初始化这些插槽。在该数组上进行堆排序(时间= k log k)。
2。然后提取第一个元素,将其添加到最终列表中。
3。将相应列表中的第一个元素替换为其下一个元素。如果下一个元素为null,请减小堆大小并将其替换为堆中的最后一个元素。 (时间= O(1))。
4。执行最大堆操作(时间= O(log k))。 重复整个2-3-4的过程,直到用尽所有列表。
因此,时间= 1.heap-sort + 2.max-element 3.Replacement + 4.max-heapify。 = O(k log k)+ O(1)+ O(1)+ n * O(log k) <= O(n log k)。