题目描述
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例1:
输入: cost = [10,15,20]
输出: 15
解释: 你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例2:
输入: cost = [1,100,1,1,1,100,1,1,100,1]
输出: 6
解释: 你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。
提示
- 2 < = c o s t . l e n g t h < = 1000 2 <= cost.length <= 1000 2<=cost.length<=1000
- 0 < = c o s t [ i ] < = 999 0 <= cost[i] <= 999 0<=cost[i]<=999
方法:动态规划
解题思路
-
确定 dp 数组以及下标的含义
dp[i] 的定义:达到第 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[i]由 dp[i - 1],dp[i - 2] 推出,既然初始化所有的 dp[i] 是不可能的,那么只 初始化 dp[0] 和 dp[1] 就够了,其他的最终都是 dp[0]、dp[1]推出。所以初始化代码为:
dp[0] = 0, dp[1] = 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 dp[i] 1 100 2 3 3 103 4 5 104 6
代码
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
vector<int> dp(n);
dp[0] = cost[0], dp[1] = cost[1];
for(int i = 2; i < n; i++) {
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i];
}
return min(dp[n - 1], dp[n - 2]);
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( n ) O(n) O(n)。