分治算法和动态规划算法的区别是什么?这两个术语有什么不同?我不明白它们之间的区别。

请举一个简单的例子来解释两者之间的区别,以及它们相似的理由。


当前回答

我认为分治法是递归方法,动态规划是表填充。

例如,归并排序是一种分治算法,因为在每一步中,您将数组分成两部分,递归地在两部分上调用归并排序,然后合并它们。

Knapsack是一种动态规划算法,因为您正在填充表示整个背包子问题的最优解的表。表中的每一项都对应于给定物品1-j的袋子中所能携带的最大重量w。

其他回答

分而治之和动态规划的另一个区别是:

分而治之:

在子问题上做更多的工作,因此有更多的时间消耗。 分治法中子问题是相互独立的。

动态规划:

只解决一次子问题,然后将其存储在表中。 在动态规划中,子问题不是相互独立的。

我认为分治法是递归方法,动态规划是表填充。

例如,归并排序是一种分治算法,因为在每一步中,您将数组分成两部分,递归地在两部分上调用归并排序,然后合并它们。

Knapsack是一种动态规划算法,因为您正在填充表示整个背包子问题的最优解的表。表中的每一项都对应于给定物品1-j的袋子中所能携带的最大重量w。

分治法在每一级递归中涉及三个步骤:

把问题分成子问题。 通过递归求解子问题来克服子问题。 将子问题的解合并到原问题的解中。 这是一种自顶向下的方法。 它在子问题上做更多的工作,因此有更多的时间 消费。 如。斐波那契数列的第n项可以用O(2^n)个时间复杂度计算。

动态规划包括以下四个步骤: 1. 描述最优解的结构。 2. 递归地定义最优解的值。 3.计算最优解的值。 4. 从计算的信息构造一个最优解。

这是一种自底向上的方法。 由于我们使用了之前计算的值,而不是再次计算,因此比分治算法花费的时间更少。 如。斐波那契数列的第n项可以用O(n)个时间复杂度来计算。

为了便于理解,让我们将分而治之视为一种暴力解决方案,并将其优化视为动态规划。 注意:具有重叠子问题的分治算法只能用dp进行优化。

分而治之

分而治之的工作原理是将问题划分为子问题,递归地征服每个子问题,并将这些解决方案组合起来。

动态规划

动态规划是一种解决具有重叠子问题的问题的技术。每个子问题只解决一次,每个子问题的结果存储在一个表中(通常实现为数组或哈希表),以供将来引用。这些子解可以用来获得原始解,存储子问题解的技术称为记忆。

你可能会想到DP =递归+重用

理解差异的一个经典例子是,这两种方法都可以获得第n个斐波那契数。看看麻省理工学院的材料。


分而治之法

动态规划方法

动态规划与分治的相似之处

在我看来,现在我可以说动态规划是分而治之的范例的扩展。

我不会把它们视为完全不同的东西。因为它们都是通过递归地将一个问题分解为两个或多个相同或相关类型的子问题,直到它们变得足够简单可以直接解决。然后将子问题的解组合起来给出原始问题的解。

那么为什么我们仍然有不同的范式名称,为什么我称动态规划为扩展。这是因为只有当问题具有一定的限制条件或先决条件时,才可以应用动态规划方法。在此基础上,动态规划利用记忆法和制表法对分治法进行了扩展。

让我们一步一步来……

动态规划先决条件/限制

正如我们刚刚发现的,为了使动态规划适用,分治问题必须具有两个关键属性:

最优子结构-最优解可以由其子问题的最优解构造 重叠子问题——问题可以分解为多次重用的子问题,或者问题的递归算法可以一遍又一遍地解决相同的子问题,而不是总是生成新的子问题

一旦满足这两个条件,我们就可以说这个分治问题可以用动态规划方法来解决。

分而治之的动态规划扩展

动态规划方法通过两种技术(记忆和制表)扩展了分而治之的方法,这两种技术都具有存储和重用子问题解决方案的目的,可以极大地提高性能。例如,斐波那契函数的朴素递归实现的时间复杂度为O(2^n),而DP解决方案只需要O(n)时间就可以完成同样的工作。

记忆(自顶向下缓存填充)是指缓存和重用先前计算结果的技术。因此,记忆fib函数看起来像这样:

memFib(n) {
    if (mem[n] is undefined)
        if (n < 2) result = n
        else result = memFib(n-2) + memFib(n-1)
        
        mem[n] = result
    return mem[n]
}

制表(自底向上的缓存填充)与此类似,但重点是填充缓存的条目。计算缓存中的值最简单的方法是迭代。fib的制表版本是这样的:

tabFib(n) {
    mem[0] = 0
    mem[1] = 1
    for i = 2...n
        mem[i] = mem[i-2] + mem[i-1]
    return mem[n]
}

你可以在这里读到更多关于记忆和制表比较的内容。

这里您应该掌握的主要思想是,由于我们的分治问题具有重叠的子问题,因此可以缓存子问题的解决方案,从而实现记忆/制表。

那么到底DP和DC有什么区别呢

既然我们现在已经熟悉了DP的先决条件和它的方法,我们就可以把上面提到的所有内容放在一张图中了。

如果你想看代码示例,你可以看看这里更详细的解释,你会发现两个算法示例:二进制搜索和最小编辑距离(Levenshtein Distance),它们说明了DP和DC之间的区别。