为什么划分和征服快速减少以解决合并K排序列表

时间:2018-06-16 10:00:31

标签: python algorithm fold divide-and-conquer

我正在使用方法5:Merge with Divide And Conquer来解决leetcode中的合并K排序问题。该算法非常快,大约需要100ms。但是,我不明白为什么reduce方法运行时间要慢得多(4000 + ms)。

这是代码差异:

# reduce
import functools
return functools.reduce(_mergeTwoLists, lists)

# divide and conquer
step = 1
while step < num:
   for i in range(0, num - step, step * 2):
       lists[i] = _mergeTwoLists(lists[i], lists[i + step])
   step *= 2
   return lists[0]

如果分崩离析在parallel中运行,我可以理解为什么分而治之的速度更快,但我认为它应该仍然是线性的,对吗?

我还写了另一个昂贵版本的merge来测试diff:

  def add(a, b):
       tmp = 0
       for i in range(1, 5000):
           tmp += i
       return a + b 

reducedivide and conquer的此版本运行时间几乎完全相同。

是否存在reduce无法处理的合并K排序列表测试用例? 是否存在我在分而治之中缺少的东西?

1 个答案:

答案 0 :(得分:0)

这两种方法的复杂性是不同的。两倍合并是O(m + n),其中m和n是两个列表的长度。

划分和征服需要O(log N - log J)迭代(N =元素总数,J =我们开始的子列表长度)每次迭代都是O(N),因为每个元素只涉及一个合并 - &GT;总O(N(log N - log J))

reduce采用N / J - 1步复杂度O(2J),O(3J),O(4J)。因此总复杂度为O(N ^ 2 / J)

请注意,在两种情况下,两次合并的总数是相同的,不同之处在于分而治之的合并平均更便宜。

这与你的观察结果一致,即用加法替换两次合并会产生大致相等的运行时间,因为加法的成本基本上与操作数无关(我认为你是在添加数字,而不是列表?),尤其是当它是被燃烧时间循环淹没。