题目
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
示例 1:
输入:cost = [10, 15, 20] 输出:15 解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15
。 示例 2:输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 输出:6 解释:最低花费方式是从
cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。提示:
cost 的长度范围是 [2, 1000]。 cost[i] 将会是一个整型数据,范围为 [0, 999]
思路
动规五部曲:
- 确定
dp
数组以及下标的含义
dp[i]
的定义:到达第i
个台阶所花费的最少体力为dp[i]
- 确定递归公式
(因为仍然是一次走一步或者一次走两步)可以有两个途径得到dp[i]
,一个是dp[i-1]
一个是dp[i-2]
,并且一定是选最小的(不像爬楼梯求的是方法的总和所以是累加):dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
dp
数组如何初始化
这里要初始化所有的dp[i]
是不可能的,因为不可能初始化为第i
台阶花费的最少体力
dp[0] = cost[0];
dp[1] = cost[1];
- 确定遍历顺序
因为是模拟台阶,而且dp[i]
由dp[i-1]
和dp[i-2]
推出,所以是从前到后遍历cost
数组就可以了 - 举例推导dp数组(很重要,最好自己在草稿纸上模拟一遍)
拿示例2:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] ,来模拟一下dp数组的状态变化:
i = [0, 1 , 2, 3, 4, 5, 6, 7, 8, 9]
cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
//推导如下
dp[i] = min(dp[i-1],dp[i-2]) + cost[i]
dp[0] = cost[0] = 1;
dp[1] = cost[1] = 100;
dp[2] = 1 + 1 = 2
dp[3] = 2 + 1 = 3
类似...
java代码如下:
class Solution {//第一步不支付费用
public int minCostClimbingStairs(int[] cost){
int[] dp = new int[cost.length];
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]);//这里相当于返回最后一步和倒数第二步所要花费的最小值,因为从这两个地方都可以直接到达终点
}
}