我正在使用方法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
reduce
和divide and conquer
的此版本运行时间几乎完全相同。
是否存在reduce
无法处理的合并K排序列表测试用例?
是否存在我在分而治之中缺少的东西?
答案 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)
请注意,在两种情况下,两次合并的总数是相同的,不同之处在于分而治之的合并平均更便宜。
这与你的观察结果一致,即用加法替换两次合并会产生大致相等的运行时间,因为加法的成本基本上与操作数无关(我认为你是在添加数字,而不是列表?),尤其是当它是被燃烧时间循环淹没。