简单动态规划问题思路分析

一、问题引入

1. 斐波那契数列(Fibonacci Sequence)

        F(0) = 1, F(1) = 1.......F(n) = F(n-1) + F(n-2)

        最简单的编程实现算法为:

def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n-1) + fib(n-2)

        我们可以测试下当 n = 10, n = 20 , n =40 时,程序运行时间成指数级增长,说明此算法的时间复杂度为指数级。

  下面我们分析下上面递归函数的执行过程,如下图所示:


        不难发现,在递归计算中存在重复计算,如浅蓝色圆圈圈出的部分,就重复计算了三次。在此基础上我们可以对上一版的递归程序进行改进,使得重复计算的部分均只计算一次。

        一个简单的方法就是 创建一个memo数组,存放计算的fib(n) 的值,如果 传入的 n已经计算过,便直接返回值,若没被计算,便将计算后得到的值存入到memo数组中。这样保证了每次n只计算一次,不用每次都递归求解 n 对应的fib值。

        此方法成为 记忆化搜索:

n = 40
memo = [-1 for i in range(n+1)]
def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    if memo[n] != -1:
        return memo[n]
    memo[n] = fib(n-1) + fib(n-2)
    return memo[n]

a = fib(n)
print(a)

二、动态规划

        上面的两种方法均基于递归的思想,即自上而下的解决问题。假设子问题已经得到解决,并设置终止条件,从而得到最终问题的解。

        而动态规划问题的思想是自下而上的的解决问题,由最初的子问题一步步得到最终的结果。

        动态规划算法:

def fib(n):
    memo = [0 for i in range(n+1)]
    memo[0] = 0
    memo[1] = 1
    for i in range(2, n+1):
        memo[i] = memo[i-1] + memo[i-2]
    return memo[n]

a = fib(55)
print(a)

        有了记忆化搜索为什么还需要动态规划???动态规划可以最少的循环次数(递归方法对应的就是递归次数)来实现问题的求解,我们可以写程序比较两者的执行时间和程序循环次数。至于为什么动态规划会比递归少,暂时还没想明白。

        因此,动态规划整体上是优于记忆化搜索的。

三、动态规划介绍

        维基百科定义:将原问题拆解成若干子问题,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案

        我们可以用一张图来表示递归问题,记忆化搜索, 动态规划 三者之间的联系与区别



参考:

慕课网 刘宇波《玩转算法面试》课程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值