1.4动态规划初步

动态规划

  • DSA的优化

Make it work, make it right, make it fast.
— Kent Beck

  • 前两步可以通过递归实现,优化可采取迭代,
  • 从某种意义上来讲,动态规划就是通过递归,找出算法的本质,给出问题的初步解,再将其等效得转化为迭代的形式。

斐波那契数列的计算

  • 法一:递归
    • 效率过低,原因在于计算每一项时要重复计算已经计算过的数字,复杂度为O(2^n)
int fib(n) { return (2>n) ? n : fib(n-1) + fib(n-2); }
  • 法二:记忆法(memoization)

    • 将已计算过实例的结果制表查询
  • 法三:动态规划(dynamic programming)

    • 颠倒计算方向:由自顶向下递归,改为自底向上迭代
    int f = 0, g = 1;//fib(0), fib(1)
    while(n--){
    	g = g + f;//不断迭代,使他们始终指向斐波那契数列中当前相邻的两项
    	f = g - f;
    }
    return g;
    

最长公共子序列

  • 子序列(Subsequence):由序列中若干字符,按原相对次序构成
  • 最长公共子序列(Longest Common Subsequence):两个序列公共子序列中的最长者
    • 可能有多个,可能有歧义(同一个字符由一个序列中的不同位置的字符均可提供)
      最长公共子序列
递归法
  • 对于序列A[0, n]和B[0, m],LCS(A, B)有三种情况
    • 递归基:若n = -1或m = -1,则取作空序列("")
    • 减而治之:若A[n] = ‘X’ = B[m], 则取作LCS(A[0, n], B[0, m)) + ‘X’
    • 分而治之:若A[n] != B[m], 则在 LCS(A[0,n], B[0,m))与LCS(A[0,n),B[0,m])中取更长者
  • 复杂度分析
    • 单调性:无论如何,每经过一次比对,原问题的规模必可减小,具体的,作为输入的两个序列,至少其一的长度缩短一个单位
    • 最好情况(不出现分而治之情况)下,只需要O(n+m)时间
    • 问题在于,(在分而治之情况下)原问题将分解为两个子问题,两个子问题的规模之和,大致是原问题的两倍,且它们在随后进一步导出的子问题,可能雷同
    • 复杂度O(2^n)
迭代法
  • 采用动态规划的策略,只需要O(n*m)时间即可计算出所有的子问题
    • 将所有的子问题(假想地)列成一张表
    • 颠倒计算方向,从LCS(A[0], B[0])出发,依次计算出所有项
总结
  • 递归:设计出可行且正确的解
  • 动态规划:消除重复的计算,提高效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值