为什么我们通常在分而治之的算法中分为两部分?

时间:2017-10-23 08:56:57

标签: algorithm data-structures

在合并排序中,我们在解决时分为两部分。为什么我们没有将它分成3个或更多部分?同样在我看到的许多分而治之的问题中,人们往往分为两部分。为什么不是3个或更多部分?它对解决方案/复杂性有什么影响?

4 个答案:

答案 0 :(得分:3)

将问题分成3个或更多部分通常不方便,并且对算法的复杂性没有影响。它通常会对实际性能产生负面影响,因为更复杂的代码在实践中往往效率低于简单的简化代码。但情况并非总是如此。

有一些实用的D& C算法可以将问题分成两部分以上,因为这样做很有帮助。双枢轴快速排序就是一个例子。与常规快速排序相比,它往往更快(通过常数因素)。

答案 1 :(得分:1)

你可以。但这并不重要。将产生除以log_2的复杂性(让我们来谈谈它)。

准确地说,您获得了log,但它被推广到log_a,因为复杂性分析中的常数因素无关紧要 Big-O-Notation < / strong>,Wikipedia)。而且您只需使用常数因子即可将log_b转换为log_a(x) = log_b(x) * (1 / log_b(a))

2

在一个更具体的层面上,当你分成两半时,你会得到4常数因子。如果您现在拆分为2,那么您将替换type Indexable<TKey, TValue> = { [index: TKey]: TValue } ,但实际上这只是一个常数因素变化,无论如何。

在使用并行分布式编程时,实际上通常会分成两个以上的部分。

但除此之外,分而治之只是一种让人们更容易理解问题的技巧。你将一个更难的问题转化为更容易解决的小问题。

大多数时候分而治之的唯一好处就是它更容易理解。

答案 2 :(得分:1)

因为实现复杂性与时间复杂度之间存在权衡关系。

让我们通过一个例子来理解它,以及&#34;划分&#34;作品。假设我们有n个元素,我们必须在其中执行一些算法。让我们看看线性和对数复杂性的差异。

比如说n~10^6,那么数据集上的任何线性函数都需要大约10^6 * t个时间单位,其中t是处理一个数据点所花费的时间。对于分而治之的方法,这会减少到log(10^6) * t个单位的时间。这取决于log的基数值,在分而治之算法中,它只是&#34;部分的数量&#34;我们将数据集划分为。

让我们看一下不同基数的日志数字。

   base                log 10^6 in base

    2                   20
    3                   12.6
    4                   10

因此,我们可以看到,分成更多部分实际上并没有减少那么多时间,因为对于数据集中的10 ^ 6个元素,你进行20次迭代或者12次或10次迭代,它没有&#39; t有所作为,但将它与10 ^ 6(O(n)-complex)进行比较,你会看到它。

现在,让我们看看如果我们分成3个部分并使用它会发生什么。它的实现比使用2个部分要复杂得多。我们无法实现任何重大的时间下降,但实施将需要我们始终保持计数器以了解我们正在使用的部分。在二进制分发中,我们可以轻松地使用布尔状态来维护此计数器,因为它很直观。

另外,正如其他人在答案中解释的那样,日志基础并没有改变时间复杂度的理论大O因子。

答案 3 :(得分:0)

您可以并且有时会实施。然而,对于big-O符号,算法的最坏情况复杂度仍然相同。

显然,除法和同步算法本质上是递归的,所以你仍然会分解,直到问题处于一个微不足道的状态(基本情况 - 例如对两个数字进行排序)。你可能会很快到达这个案子,但要做更多的工作才能到达那里,在最坏的情况下,他们的表现会相同。

请参阅以下内容,因为此问题已在网上提出,人们提供了比我更好,更完整的答案: https://softwareengineering.stackexchange.com/questions/197107/divide-and-conquer-algorithms-why-not-split-in-more-parts-than-two

希望这有帮助!

同样来自上面我特别关注的链接:

  

&#34;另一方面,一些树形数据结构确实使用高   但是,分支因子(远大于3,通常为32或更多)   通常是出于其他原因。它提高了内存的利用率   层次结构:存储在RAM中的数据结构可以更好地利用缓存,   存储在磁盘上的数据结构需要较少的读取HDD-> RAM。&#34;