第十四天打卡——动态规划

动态规划五步曲:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

509. 斐波那契数 

动规五部曲:

1、明确dp数组的含义和下标

        dp[i]:下标为i(第i+1个数)的斐波那契数值为dp[i]。

2、确定递推公式

        dp[i] = dp[i-1] + dp[i-2] (i >=2)

3、初始化dp数组

        dp[0] = 0; dp[1] = 1

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)


70. 爬楼梯 

动规五部曲:

1、明确dp数组的含义和下标   很重要,做题关键!

        dp[ i ]:需要爬 i 阶才能到楼顶,这 i 阶有 dp[ i ] 种方式可以爬到楼顶

2、确定递推公式     关键!

        dp[i] = dp[i-1] + dp[i-2] (i >=3)

首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶就是dp[i]了。

其次是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶就是dp[i]了。

所以dp[ i ]是 dp[i - 1]与dp[i - 2]之和

tip:在推导dp[i]的时候,一定要时刻想着dp[i]的定义,否则容易跑偏。 

3、初始化dp数组

        dp[0] = 0; dp[1] = 1; dp[2] = 2;

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)


746. 使用最小花费爬楼梯 

和前两题一样,很常规很简单,一刷ac

动规五部曲:

1、明确dp数组的含义和下标

        dp[i]:从第i个台阶向上爬到楼顶的最低花费是dp[ i ]。

2、确定递推公式

        dp[i] = min ( dp [i +1] + dp [i + 2] )(i >=0)

3、初始化dp数组

        dp[dp.length - 1] = cost[cost.length - 1]; dp[dp.length - 2] = cost[cost.length - 2]

4、明确遍历顺序

        从后向前

5、打印dp数组(debug验证用)


62.不同路径 

方法一:动态规划

动规五部曲:

1、明确dp数组的含义和下标   重要

        dp[ i ][ j ]:从最左端( dp[0][0] )到达第i行,第j列( dp[i][j] )格子,总共有dp[ i ][ j ]条路径。

2、确定递推公式  关键

        dp[i][j] = dp [i -1][j] + dp [i][j-1] (向右+向下

3、初始化dp数组  重要

       不同于前两题,本题根据题目分析初始化dp数组,需要初始化整个第1行和第1列。

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)

方法二:数论

例如m = 3,n = 7

无论怎么移动,都有向下走两步,向右走6步,一共走8步。

所以就转换成了组合问题:C_{m-n+2}^{m-1}。


63. 不同路径 II 

和上一题类似,关键点主要在dp数组初始化上。

动规五部曲:

1、明确dp数组的含义和下标   

        dp[ i ][ j ]:从最左端( dp[0][0] )到达第i行,第j列( dp[i][j] )格子,总共有dp[ i ][ j ]条路径。

2、确定递推公式  

        如果obstacleGrid[i][j] == 1,则dp[i][j] = 0,否则 dp[i][j] = dp [i -1][j](向右) + dp [i][j-1](向下)  

3、初始化dp数组      关键!!

        不同于上一题,本题初始化第1行和第1列时,一但出现有障碍(obstacleGrid[i][j] == 1)的情况,该行或该列往后的所有值都为0。(有障碍,无法到达)

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)


343. 整数拆分 

动规五部曲:

1、明确dp数组的含义和下标   

        dp[ i ]:数字 i 被拆分后获得的最大乘积是dp[ i ]。

2、确定递推公式     难点及关键点!!

        dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));       

dp[i]可以通过两种渠道得到:

        1、j * (i - j) 直接相乘。

        2、j * dp[i - j],相当于是拆分(i - j),dp[i - j] 可能由多个数组成。  

        在取最大值的时候,还要比较dp[i]。在递推公式推导的过程中,每次计算dp[i],取最大的而已。

3、初始化dp数组      

        只初始化dp[1]和dp[2]

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)


96.不同的二叉搜索树 

动规五部曲:

1、明确dp数组的含义和下标   

        dp[ i ]:i个不同元素节点组成的二叉搜索树的个数为dp[i] 。

2、确定递推公式     难点及关键点!!

记住吧……

        dp[i] += dp[j - 1] * dp[i - j];  j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量。j从1 开始遍历到 i 为止。

dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量

元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量

有2个元素的搜索树数量就是dp[2]。

有1个元素的搜索树数量就是dp[1]。

有0个元素的搜索树数量就是dp[0]。

所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

3、初始化dp数组      

        dp[0]=1

4、明确遍历顺序

        从前向后

5、打印dp数组(debug验证用)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值