算法(01)--动态规划详解


动态规划问题的⼀般形式就是 求最值。动态规划其实是运筹学的⼀种最优化⽅法,只不过在计算机问题上应⽤⽐较多,⽐如说让你求最⻓递增⼦序列 ,最⼩编辑距离呀等等。 既然是要求最值,核⼼问题是什么呢?

求解动态规划的核⼼问题是穷举。因为要求最值,肯定要把所有可⾏的答案穷举出来,然后在其中找最值呗。

⾸先,动态规划的穷举有点特别,因为这类问题存在「重叠⼦问题」,如果 暴⼒穷举的话效率会极其低下,所以需要「备忘录」或者「DP table」来优 化穷举过程,避免不必要的计算。 ⽽且,动态规划问题⼀定会具备「最优⼦结构」,才能通过⼦问题的最值得到原问题的最值。

另外,虽然动态规划的核⼼思想就是穷举求最值,但是问题可以千变万化, 穷举所有可⾏解其实并不是⼀件容易的事,只有列出正确的「状态转移⽅程」才能正确地穷举。

在实际的算法问题中,写出状态转移⽅程是最困难的,这也就是为什么很多朋友觉得动态规划问题困难的原因,我 来提供我研究出来的⼀个思维框架,辅助你思考状态转移⽅程:

明确「状态」 -> 定义 dp 数组/函数的含义 -> 明确「选择」-> 明确 base case。

《斐波那契数列》— 主要是让你明⽩什么是重叠⼦问题

1.1) 暴⼒递归

斐波那契数列的数学形式就是递归的,写成代码就是这样:

    int	fib(int	N){
   
    if(N ==	1 || N	==	2) return 1;
    return	fib(N-1) + fib(N-2);
}

PS:但凡遇到需要递归的问题,最好都画出递归树,这对你分析算法的复杂度,寻找算法低效的原因都有巨⼤帮助。

想要计算原问题f(20),我就得先计算出⼦问题f(19)和f(18),然后要计算f(19),我就要先算出⼦问题f(18)和 f(17),以此类推。最后遇到f(1)或者f(2)的时候,结果已知,就能直接返回结果,递归树不再向下⽣⻓了。

递归算法的时间复杂度怎么计算?⼦问题个数乘以解决⼀个⼦问题需要的时间

⼦问题个数,即递归树中节点的总数,显然⼆叉树节点总数为指数级别,所以⼦问题个数为O(2^n)。
解决⼀个⼦问题的时间,在本算法中,没有循环,只有f(n-1)+f(n-2)⼀ 个加法操作,时间为O(1)。 所以,这个算法的时间复杂度为O(2^n),指数级别,爆炸。

观察递归树,很明显发现了算法低效的原因:存在⼤量重复计算,⽐如f(18)被计算了两次,⽽且你可以看到,以f(18)为根的这个递归树体量巨⼤,多算⼀遍,会耗费巨⼤的时间。更何况,还不⽌f(18)这⼀个节点 被重复计算,所以这个算法及其低效。
这就是动态规划问题的第⼀个性质:重叠⼦问题。下⾯我们想办法解决这个问题。

1.2) 带备忘录的递归解法

明确了问题,其实就已经把问题解决了⼀半。即然耗时的原因是重复计算, 那么我们可以造⼀个「备忘录」,每次算出某个⼦问题的答案后别急着返 回,先记到「备忘录」⾥再返回;每次遇到⼀个⼦问题先去「备忘录」⾥查 ⼀查,如果发现之前已经解决过这个问题了,直接把答案拿出来⽤,不要再耗时去计算了。
⼀般使⽤⼀个数组充当这个「备忘录」,当然你也可以使⽤哈希表(字 典),思想都是⼀样的。

    int fib(int N) {
   
        if (N < 1) return 0;
        //	备忘录全初始化为0
        vector<int> memo (N + 1, 0);
        //	初始化最简情况
        return helper(memo, N);
    }

    int helper(vector<int>& memo, int n) {
   
        //	base	case
        if (n == 1 || n == 2) return 1;
        //	已经计算过
        if (memo[n] != 0) return memo[n];
        memo[n
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值