为啥分而治之的算法通常比蛮力运行得更快?

Posted

技术标签:

【中文标题】为啥分而治之的算法通常比蛮力运行得更快?【英文标题】:Why do divide and conquer algorithms often run faster than brute force?为什么分而治之的算法通常比蛮力运行得更快? 【发布时间】:2012-06-18 02:01:00 【问题描述】:

为什么分而治之的算法通常比蛮力运行得更快?例如,查找最近的一对点。我知道你可以给我看数学证明。但直觉上,为什么会发生这种情况?魔法?

理论上,“分而治之总是胜于蛮力”是真的吗?如果不是,有反例吗?

【问题讨论】:

把一个蛋糕分成16块,第一个解决办法是试着把蛋糕切成1/16等等……很难。另一种解决方案是将蛋糕切成 2 块,然后再切成 2 块,然后分别切成 2 块中的 1/4 和 2 块中的 1/8。 【参考方案1】:

对于您的第一个问题,分而治之背后的直觉是,在许多问题中,必须完成的工作量是基于输入的某些组合属性,而不是线性扩展。

例如,在最近的点对问题中,蛮力答案的运行时间取决于您必须查看所有 O(n2) 可能的点对的事实.

如果你把一个二次增长的东西切成两块,每块都是以前的一半大小,每半块解决问题需要初始时间的四分之一,所以两半解决问题所需时间大约是蛮力解决方案所需时间的一半。把它切成四块需要四分之一的时间,把它切成八块需要八分之一的时间,等等。

在这种情况下,递归版本最终会更快,因为在每一步中,我们通过确保没有太多我们实际需要检查的元素对来避免处理元素对的大量工作。由于类似的原因,大多数具有分而治之解决方案的算法最终会更快。

对于第二个问题,不,分而治之算法不一定比蛮力算法快。考虑在数组中找到最大值的问题。蛮力算法需要 O(n) 时间并使用 O(1) 空间,因为它对数据进行线性扫描。这里给出了分治算法:

如果数组只有一个元素,那就是最大值。 否则: 将阵列切成两半。 找出每一半的最大值。 计算这两个值的最大值。

这也需要 O(n) 时间,但堆栈空间使用 O(log n) 内存。它实际上比简单的线性算法更糟糕。

再举一个例子,maximum single-sell profit problem 有一个分而治之的解决方案,但优化的动态编程解决方案在时间和内存上都更快。

希望这会有所帮助!

【讨论】:

【参考方案2】:

我建议你通读算法设计的第5章,它很好地解释了分而治之。

直观地说,对于一个问题,如果你能把它分成两个与源问题相同模式的子问题,并且将两个子问题的结果合并成最终结果的时间复杂度会小一些,那么它比通过蛮力解决原始完整问题要快。

正如算法设计中所说,实际上你并不能从分而治之中获得太多时间,一般你只能将时间复杂度从较高的多项式降低到较低的多项式(例如从 O (n^3) 到 O(n^2)),但几乎没有从指数到多项式(例如从 O(2^n) 到 O(n^3))。

我认为你可以从分而治之中获得的最大收获是解决问题的心态。将最初的大问题分解为更小、更容易的子问题总是一个很好的尝试。即使你没有得到更好的运行时间,它仍然可以帮助你思考问题。

【讨论】:

以上是关于为啥分而治之的算法通常比蛮力运行得更快?的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的 python 程序运行得更快?

一个“分而治之”的算法分配

计算优势点的分而治之算法?

为啥二分搜索是一种分而治之的算法?

矩阵乘法 - 分而治之 vs Strassen,分而治之更快?

为啥这个计数器以这种方式增加,而不是在这个分而治之的算法中一个一个增加?