7.01 动态规划01

186 阅读1分钟

1 . 动态规划一般解决的问题

  • 动归基础问题 (斐波那契 ,上台阶)
  • 背包问题
  • 打家劫舍
  • 股票问题
  • 子序列

2 . 动归五部曲

  • 声明 dp 数组 ,明白数组下标含义
  • 确定递推(状态转移)公式
  • dp 数组的初始化
  • 确定遍历顺序
  • 打印 dp 数组 ,检验解题思路正确与否

3 . 例题

3 . 1 上台阶问题

[](剑指 Offer 10- II. 青蛙跳台阶问题 - 力扣(LeetCode))

0405.png

分析 :

该题解法与斐波那契数列一样 ,因为 上 n 阶的方法 = 上 n - 1 阶的方法 + 上 n - 2 阶的方法 ,因为 最后一步无非就是从第 n - 1 阶上到第 n 阶 或者从第 n - 2 阶上到第 n 阶。

3 . 2 股票的最大利润

[](剑指 Offer 63. 股票的最大利润 - 力扣(LeetCode))

0406.png

分析 :第 i 天的最大利润 = 第 i 天股票 - 第 i - 1 天股票 + 第 i - 1 天最大利润 *

  • dp 数组下标的含义 dp[ i ] 表示第 i 天卖获得的最大利润 ,不是前 i 天获得的最大利润 。
  • 递推公式 : dp[ i ] = prices[ i ] - prices[ i-1 ] + dp[ i-1 ] ;
  • 注意 : 如果 dp[ i ] < 0 ; dp[ i ] = 0;
  • 在遍历过程中 ,用 max 比较记录最大值

3 . 3 连续子数组的最大和

剑指 Offer 42. 连续子数组的最大和 - 力扣(LeetCode)

0407.png

  • dp[ i ] 表示到第 i 个位置为止最大的连续子数组的最大和
  • dp[ i ] = max( dp[ i - 1 ] + nums[ i ] , nums[ i ] )
  • 初始化 dp[ 0 ] = nums[ 0 ]
  • 遍历过程中 ,用 max 比较记录最大值。

3 . 4 礼物的最大值

[](剑指 Offer 47. 礼物的最大价值 - 力扣(LeetCode))

0408.png

分析 : 到达dp[ i ][ j ] 就只有两条路 ,从上面 dp[ i - 1 ][ j ]过来 or 从左面 dp[ i ][ j - 1 ]过来。

  • grid[ k ][ l ] = Math.max(grid[ k - 1 ][ l ],grid[ k ][ l - 1 ]) + grid[ k ][ l ]

  • 初始化时 ,记得是初始化第一行和第一列

3 . 5 把数字翻译成字符串

[](剑指 Offer 46. 把数字翻译成字符串 - 力扣(LeetCode))

0409.png

分析 : dp[ i ] 表示到第 i 个数字时 ,有几种方法。每次多考虑一位 ,此时就要考虑两种情况 , 多加的一位 i 跟前面的 i - 1 位组成的数字 小于26且大于等于10 , 此时翻译的方法就会变多 ,且多的方法数量为 dp[ i - 2 ] ; else 此时多加的一位没有什么用 ,前面 i - 1位有几种翻译方法 ,它就有几种 ,因为只不过是在前 i - 1 位翻译的后面多加一个字母而已 。

所以 :

for(var i = 2 ; i < length ; i++)
 {
        if((nums[i-1]-'0')*10+(nums[i]-'0') <= 25&&(nums[i-1]-'0')*10+(nums[i]-'0')>=10)
        dp[i] = dp[i-1] + dp[i-2];
        else
        dp[i] = dp[i-1];
 }