递归、分治策略、动态规划以及贪心算法之间的关系

本人原创,转载请注明出处:http://blog.csdn.net/tyhj_sf/article/details/53969072

引言

最近集中研究计算智能,其中涉及到递归和动态规划,动态规划实现中又用到了递归,忽然发现这两个概念的差别分得不太清楚。索性把递归、分治策略、动态规划、贪婪选择之间的联系与区别都一并搞清楚吧。

1、分治策略(Divide and Conquer)

将原问题分解为若干个规模较小但类似于原问题的子问题(Divide),递归的求解这些子问题(Conquer),然后再合并这些子问题的解来建立原问题的解。因为在求解大问题时,需要递归的求小问题,因此一般用递归的方法实现,即自顶向下。

2、动态规划(Dynamic Programming)

动态规划其实和分治策略是类似的,也是将一个原问题分解为若干个规模较小的子问题,递归的求解这些子问题,然后合并子问题的解得到原问题的解。区别在于这些子问题会有重叠,一个子问题在求解后,可能会再次求解,于是我们想到将这些子问题的解存储起来,当下次再次求解这个子问题时,直接拿过来就是。其实就是说,动态规划所解决的问题是分治策略所解决问题的一个子集,只是这个子集更适合用动态规划来解决从而得到更小的运行时间。即用动态规划能解决的问题分治策略肯定能解决,只是运行时间长了。因此,分治策略一般用来解决子问题相互对立的问题,称为标准分治,而动态规划用来解决子问题重叠的问题

动态规划一般由两种方法来实现,一种为自顶向下的备忘录方式,用递归实现,一种为自底向上的方式,用迭代实现。

3、贪心算法(Greedy Algorithm)

贪心算法在每一步都做出最优的选择,希望这样的选择能导致全局最优解。对,只是寄希望,因此贪心算法并不保证得到最优解,但是它对很多问题确实可以得到最优解,而且运行时间更短。由此可见,贪心算法是带有启发性质的算法。那什么时候可以用贪心算法呢?当该问题具有贪心选择性质的时候,我们就可以用贪心算法来解决该问题。
贪心选择性质:我们可以通过做出局部最优(贪心)来构造全局最优。只要我们能够证明该问题具有贪心选择性质,就可以用贪心算法对其求解。比如对于0-1背包问题,我们用贪心算法可能得不到最优解(当然,也可能会得到最优解),但对于部分背包问题,则可以得到最优解,贪心算法可以作为0-1背包问题的一个近似算法。

动态规划与递归的比较

就性能而言,我用递归和动态规划实现了斐波纳契数列计算,递归如果超过40的时候就已经需要很长时间了,40次大概需要1秒左右,但是用动态规划要一亿次,才需要4秒,这个相差的可不是几个数量级的问题。事实上,递归实现的斐波那契数列计算时间复杂度为O(2ⁿ),动态规划实现时间复杂度为O(n)所以,在以后的开发中,尽量避免使用递归。
就具体实现上而言,动态规划比普通递归仅仅是多了一步保存子问题计算结果的操作。
例如,斐波那契数列的递归实现如下:

 int F(int i)
    {
             if(i < 1)  return 0;
             if(i == 1) return 1;
              return F(i-1) + F(i - 2);
    }

而用动态规划算法实现是这样:

 int F(int i)
{
     if(knownF[i] != unknown){
        return knownF[i];
     }
     if(i == 0) t = 0;
     if(i == 1) t = 1;
     if(i > 1)  t = F(i - 1) + F(i - 2);
     return knownF[i] = t;
}

4、总结

  1. 分治策略用于解决原问题与子问题结构相似的问题,对于各子问题相互独立的情况,一般用递归实现;
  2. 动态规划用于解决子问题有重复求解的情况,既可以用递归实现,也可以用迭代实现;
  3. 贪心算法用于解决具有贪心选择性质的一类问题,既可以用递归实现,也可以用迭代实现,因为很多递归贪心算法都是尾递归,很容易改成迭代贪心算法;
  4. 递归是实现手段,分治策略是解决问题的思想,动态规划很多时候会使用记录子问题运算结果的递归实现。

参考资料:
1.http://1661518.blog.51cto.com/1651518/1396943
2.《算法导论》第三版

  • 14
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 分治策略是将一个复杂的问题分解成相互独立的子问题,然后递归地解决这些子问题,最后合并子问题的解得到原问题的解;动态规划是一种在求解复杂问题时寻求最优解的通用技术,它通过把原问题分解为相互依赖的子问题来实现;贪心算法是一种在每一步都采取在当前状态下最优的选择,从而希望导致结果是最优的算法;回溯法是一种试错法,它尝试分步解决一个复杂的问题,当它发现某一步无论如何也无法得到正确解决方案时,就会回溯到前一步并重新尝试。 ### 回答2: 分治策略动态规划贪心算法和回溯法都是解决问题的常用算法思想,它们在解决问题的方式和适用场景上有不同的特点。 分治策略是将问题分解为更小的子问题,在将子问题解决后进行合并得到整体问题的解。分治策略适用于问题可以分解为相同类型的子问题,并且子问题的解可以独立求解的情况。典型的应用包括快速排序和合并排序。 动态规划是一种以自底向上的方式逐步求解问题的优化方法。它将问题划分为重叠且相互依赖的子问题,使用一张表来记录子问题的解,通过解决子问题的最优解来解决整体问题。动态规划适用于满足最优子结构和无后效性的问题,常见的应用有背包问题和最短路径问题。 贪心算法是一种选择当前最优策略的方法,并且期望通过每一步的最优选择最终得到全局最优解。贪心算法通常没有全局优化的策略,而是通过选择局部最优解来进行推进。贪心算法适用于满足贪心选择性质和最优子结构的问题,例如霍夫曼编码和最小生成树问题。 回溯法是一种通过穷举所有可能的解来寻找问题解的方法。它采用试错的方式进行搜索,并在搜索过程中通过剪枝操作来减少不必要的计算。回溯法适用于问题解空间规模较小的情况,例如八皇后问题和0-1背包问题。 综上所述,分治策略通过分解子问题并合并解决整体问题,动态规划通过记录子问题的解来逐步求解整体问题,贪心算法通过每一步的最优选择来推进解决整体问题,回溯法通过穷举所有可能的解来寻找问题解。这四种算法思想各有不同的应用场景,根据问题的特点选择合适的算法可以更高效地解决问题。 ### 回答3: 分治策略动态规划贪心算法和回溯法是算法设计中常用的四种策略。它们具有各自独特的特点和应用场景。 分治策略是将问题划分为若干个规模较小且结构相似的子问题,通过递归地解决子问题,最后合并得到原问题的解。分治策略适用于问题可以分解为独立子问题,并且合并子问题的解不会产生冲突。典型应用如归并排序和快速排序。 动态规划是通过将问题划分为相互重叠的子问题,并求解子问题的解来求解原问题。动态规划通常适用于具有最优子结构的问题,可以通过空间换时间来提高效率。通过构建状态转移方程和建立递推关系,逐步计算得到最优解。典型应用如背包问题和最短路径问题。 贪心算法是一种每一步都选择当前状态下的最优解,以求得全局最优解的策略。它通过每一步的最优选择,局部地达到全局最优。贪心算法通常适用于问题具有贪心选择性质,即每个子问题都可以通过选取局部最优解而得到全局最优解。典型应用如霍夫曼编码和最小生成树算法。 回溯法是一种通过穷举所有可能的解,并逐步构建可行解的方法。它采用试错的方式,在每一步都通过选择一个可能的解决方案,然后进行尝试。若尝试失败,则回溯到上一步重新选择。回溯法适用于问题的解空间较小,且要求找出所有可能的解或满足特定条件的解。典型应用如八皇后问题和旅行商问题。 总之,分治策略动态规划贪心算法和回溯法都是解决问题的有效策略,通过合适的选择和设计,可以在不同的问题领域中获得最优解或满足特定条件的解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值