1 . 动态规划一般解决的问题
- 动归基础问题 (斐波那契 ,上台阶)
- 背包问题
- 打家劫舍
- 股票问题
- 子序列
2 . 动归五部曲
- 声明 dp 数组 ,明白数组下标含义
- 确定递推(状态转移)公式
- dp 数组的初始化
- 确定遍历顺序
- 打印 dp 数组 ,检验解题思路正确与否
3 . 例题
3 . 1 上台阶问题
[](剑指 Offer 10- II. 青蛙跳台阶问题 - 力扣(LeetCode))
分析 :
该题解法与斐波那契数列一样 ,因为 上 n 阶的方法 = 上 n - 1 阶的方法 + 上 n - 2 阶的方法 ,因为 最后一步无非就是从第 n - 1 阶上到第 n 阶 或者从第 n - 2 阶上到第 n 阶。
3 . 2 股票的最大利润
[](剑指 Offer 63. 股票的最大利润 - 力扣(LeetCode))
分析 :第 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)
- dp[ i ] 表示到第 i 个位置为止最大的连续子数组的最大和
- dp[ i ] = max( dp[ i - 1 ] + nums[ i ] , nums[ i ] )
- 初始化 dp[ 0 ] = nums[ 0 ]
- 遍历过程中 ,用 max 比较记录最大值。
3 . 4 礼物的最大值
[](剑指 Offer 47. 礼物的最大价值 - 力扣(LeetCode))
分析 : 到达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))
分析 : 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];
}