我有圆形(n / k)排序的子列表,这意味着每个子列表的长度为k(以及长度小于k的单个列表)。我需要使用经典的O(m + n)合并函数将它们合并到一个n长度的排序列表中,因此需要O(n * log(n / k))。
我有两个实现,一个带递归(这似乎是正确的,但除非我改变递归深度,否则我将不会工作,我不被允许,而且我不明白为什么实际上,当输入列表不超过10个子列表,每个子列表的长度为k = 3):
def merge_sorted_blocks(lst):
i=0
pairs_lst=[]
n=len(lst)
while i<n-1:
pairs_lst.append(merge(lst[i],lst[i+1]))
i+=2
if n%2>0:
pairs_lst.append(lst[n-1])
if type(pairs_lst[0])!=list:
return pairs_lst
return merge_sorted_blocks(pairs_lst)
和一个连续输出列表与下一个子列表:
def merge_sorted_blocks(lst):
pairs_lst=[]
for i in lst:
pairs_lst=merge(pairs_lst,i)
return pairs_lst
但我不认为它具有所需的复杂性,更像是O(n *(k + 2k + ...))= O(n ^ 2))。 我发现这个线程表明它确实存在,但我不明白如何: https://math.stackexchange.com/questions/881599/on-log-k-for-merging-of-k-lists-with-total-of-n-elements
对于每种解决方案,我都缺少一些东西吗?
答案 0 :(得分:1)
对于第二种算法,您的计算具有谬误。此外,您提到的主题与您的问题有一些差异。
您有k
子列表,其大小为n/k
。由于大小为merge
和n1
的两个集合的n2
函数的复杂度为O(n1 + n2)
,因此两个子列表的首次合并的计算复杂度为O(2 * n/k)
,并且第三个子列表的当前子列表的复杂度为O(3 * n/k)
。因此,第二种算法的复杂性为O(2*(n/k) + 3*(n/k) + ... + k*(n/k)) = O(nk)
。
首次实施时,会遗漏一些细节。例如,如果只有一个集合(例如最后一步),则循环将失败。
此外,第一种算法的复杂性分析并不准确。如果要实现引用的算法,算法为O(n/k * log(k))
。