动态规划例题详解一
斐波那契数列(入门)
解题思路:
1.确定dp数组下标含义
2.确定动态转移方程
3.确定dp数组初始化
4.确定遍历顺序
5.举例推导遍历dp
解题代码:
/***动态规划五步走:
1.确定dp数组下标含义
2.确定动态转移方程
3.确定dp数组初始化
4.确定遍历顺序
5.举例推导遍历dp
时间复杂度O(n)
*/
class Solution {
public int fib(int n) {
//1.确定dp数组下标含义,下标i就是当前是i的F(i)
int[] dp=new int[n+1];
//2.确定动态转移方程:题目中明确给出:F(n)=F(n-1)+F(n-2):故dp[n]=dp[n-1]+dp[n-2]
//3.确定起始点,显然要得出F(n),就要先得出F(n-1)和F(n-2),依次可知F(0)和F(1)是起点,遍历顺序也可知了
//特判:
if(n==0) return 0;
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
//根据上述条件列出状态转移方程
dp[i]=dp[i-1]+dp[i-2];
}
//返回F(n)--dp[n]
return dp[n];
}
}
使用最小花费爬楼梯(入门+)
这一题似乎就比斐波那契数列难一些了,因为题目有些许绕口,一开始我陷入了无法理解题目甚至是误解题意的意思了,若这题看得有点懵杯,可以先去看leetcode70题,本题是在它的基础上加多一些难度
我们依旧按照五步走来解这道题目:
这里一开始我脑子没转过来,因为题目要求的是到楼顶的最低消费,这里的cost[i]只是附加条件,并不是动态规划的dp数组
1.确定dp数组含义和其下标i的含义:dp[i]是指第i阶阶梯
2.确定动态转移方程:得到dp[i]只能有两种途径:dp[i-1]和dp[i-2] 如何判断是哪个阶梯上来的呢? 注意题目所需要的是最低消费,所以:dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i]:因为第i阶阶梯对应的是cost[i]的体力而不是i-1或i-2的体力
3.确定初始化dp:从上述条件我们可以轻易推出: dp[0]=cost[0] dp[1]=cost[1]
4.确定数组的遍历方向:爬至楼顶,当然是选择顺序遍历啦,从低到高进行遍历
5.举例推导遍历dp(自己在控制台打印输出)
这里贴出相应代码,供读者参考讨论:
class Solution {
/***动态规划:
这里一开始我脑子没转过来,因为题目要求的是到楼顶的最低消费,这里的cost[i]只是附加条件,并不是动态规划的dp数组
1.确定dp数组含义和其下标i的含义:dp[i]是指第i阶阶梯
2.确定动态转移方程:得到dp[i]只能有两种途径:dp[i-1]和dp[i-2] 如何判断是哪个阶梯上来的呢?
注意题目所需要的是最低消费,所以:dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i]:因为第i阶阶梯对应的是cost[i]的体力而不是i-1或i-2的体力
3.确定初始化dp:从上述条件我们可以轻易推出: dp[0]=cost[0] dp[1]=cost[1]
4.确定数组的遍历方向:爬至楼顶,当然是选择顺序遍历啦,从低到高进行遍历
5.举例推导遍历dp
*/
public int minCostClimbingStairs(int[] cost) {
int n=cost.length;
int[] dp=new int[n];
dp[0]=cost[0];
if(n==1){
//特判:只有一阶阶梯,只能通过这个阶梯才能跳上去
return dp[0];
}
dp[1]=cost[1];
for(int i=2;i<n;i++){
dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i];
}
//阶梯顶有两种方式可以到达,即数组末两位,返回它们中的小值
return Math.min(dp[n-1],dp[n-2]);
}
}