题目描述
解题思路
普通写法
- 确定dp数组以及下标的含义
使用动态规划,就要有一个数组来记录状态,本题只需要一个一维数组dp[i]就可以了。
dp[i]的定义:到达第i个台阶所花费的最少体力为dp[i]。(注意这里认为是第一步一定是要花费)
- 确定递推公式
可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]。
那么究竟是选dp[i-1]还是dp[i-2]呢?
一定是选最小的,所以dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i];
也就是选出前一个阶梯或者前两个最小的体力,在加上跳到本次的体力。
- dp数组如何初始化
那么只初始化dp[0]和dp[1]就够了。
- 遍历顺序
从前向后
打印dp数组
public int minCostClimbingStairs(int[] cost) {
// dp[i] 表示到达i层所花费的最小的体力值,认为第一步也花费体力值
int[] dp = new int[cost.length];
// 初始化dp数组,低0层和第1层所花费的体力值,而最后一层不需要花费体力值
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i < cost.length; i++) {
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]; // 最小的体力值和花费跳到当前楼梯的体力值
}
return Math.min(dp[cost.length - 1], dp[cost.length - 2]);
}
优化
public int minCostClimbingStairs(int[] cost) {
int dp0 = cost[0];
int dp1 = cost[1];
for (int i = 2; i < cost.size(); i++) {
int dpi = min(dp0, dp1) + cost[i];
dp0 = dp1; // 记录一下前两位
dp1 = dpi;
}
return min(dp0, dp1);
}
另一种写法
从题目描述可以看出:要不是第一步不需要花费体力,要不就是第最后一步不需要花费体力,我个人理解:题意说的其实是第一步是要支付费用的!。因为是当你爬上一个台阶就要花费对应的体力值!
所以我定义的dp[i]意思是也是第一步是要花费体力的,最后一步不用花费体力了,因为已经支付了。
当然也可以样,定义dp[i]为:第一步是不花费体力,最后一步是花费体力的。
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length + 1];
// 默认第一步不花费体力,而最后一步花费体力
dp[0] = 0;
dp[1] = 0;
for (int i = 2; i <= cost.length; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
return dp[cost.length];
}