贪心、递归、递推以及动态规划算法的分析与对比(转:By: 夏天の冰块的BLOG)

贪心、递归、递推以及动态规划算法的分析与对比

王喆 天津市第五十五中学

【关键字】

动态规划 贪心 递归 递推 分析 说明 NOIP

【摘要】

本文通过典型例题分析出贪心算法、递归算法、递推算法以及动态规划算法的区别和相似处。以及对这几种算法的思考方法,编程方法以及“递归节省时间浪费空间,递推滚动节省空间浪费时间”的解释和举例论证。

【正文】

一、各算法的介绍

1.1贪心算法

贪心的思想可以用一句话来归纳,“每步取优”。很好理解,假设你的程序要走I=1~N共N步,那么保证你的第I步走出的是当前这一步的最优值。这样的解题方法叫做贪心算法。可见贪心算法并不是一个全面的枚举方法而是若干结果中的一种,仅仅一种而已。但这种算法是不是最优解它就不能完全保证了。

1.2递归算法

一般每个可以使用递归算法求解的题目都可以写出一个递归函数。假设这个函数是F(),那么F()应该为你可以表示你的解。而题目的主要问题就是把一个大问题转换为若干个性质相同的子问题。注意是性质相同,因为只有性质相同我们才能使用同一个函数来表示。而求解的过程是从最后一步,当然每一步都会用到比自己要小的子问题的值,那么要调用程序来求出这些子问题的解,一步步返回最后得到最后的问题的解。也可以理解为求解过程是“反向”的。因为变量会是逐渐变小的。

1.3递推算法

与递归算法一样,必定会写出一个转移方程,而每个可以用递归方法解决的问题都可以用递推方法解决。我们要做的依然是把大问题转变为性质相同的子问题的过程。而求解过程与递归方法正好相反,是从最小规模的子问题开始求解,最后求到最大规模的解。与递归不一样的是,递归可以只求我们所需要的子问题的解,而递推算法在每一步计算求解的过程中并不知道下一步需要用什么样的子问题的值,于是程序必须把所有的可能性都求出来。造成了很多的计算浪费。但递推算法有一个递归算法永远做不到的优势就是“滚动性”。当递推算法求解完第一行的子问题的时候进行第二行的处理,第二行会用到上一行的子问题值。当处理第三行的时候第一行的值就没有用了,所以我们可以把单数行的值都存到第一各数组里,双数行的值都存到第二个数组里。这样可以就可以实现滚动,原来原本要开[1..n,1..n]大小的数组现在就可以只开[1..n,1..2]大小的数组了,把空间复杂度从O(N2)的复杂度变为O(2N)的复杂度。这就是所谓的“递推省空间费时间,递归省时间费空间”的道理。

1.4动态规划算法

动态规划算法,动态规划算法可以理解为是递归算法的一个延伸。因为单纯的递归算法是会出现很多子问题的重叠的,这样还是会造成同一问题的重复运算。所以我们要找一个办法来避免重复的运算。于是就出现了动态规划。简单地说,动态规划依然是把一个大问题分为若干性质相同的子问题,而这些子问题里面会有若干的重叠。(下面的例题举例)。为了当出现子问题重叠的时候不重复运算。我们就需要把所有的已经求出的子问题都存下来,判断这个子问题是否已经算过,算过了就不要再算了。如果没算过就算一遍下次在遇到这个子问题就可以不算了。因此我们必须开出一个大小为[1..N,1..N]的数组来存储,又因为每次都有可能会遇到不同的行的子问题,所以我们必须把数组全部留住,所以就不能实现递推算法的“滚动性”。但动态规划算法可以节省大量的时间。假设所有的子问题都不重叠它的时间复杂度会和递归一样。而如果优有大量的子问题重叠,那么会发现时间复杂度会有明显的降低。可以提高运算效率,缩短运算时间。

二、           用树状图直观体现动态规划的子问题分配

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值