在nlog(n / k)中合并n / k排序列表 - python

时间:2017-12-03 02:37:12

标签: python algorithm sorting time-complexity

我有圆形(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

对于每种解决方案,我都缺少一些东西吗?

1 个答案:

答案 0 :(得分:1)

对于第二种算法,您的计算具有谬误。此外,您提到的主题与您的问题有一些差异。

您有k子列表,其大小为n/k。由于大小为mergen1的两个集合的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))