这道题用动态规划解决。这道题乍一看,含义有点模糊。有两个点要搞清楚:1)给定len个台阶的梯子,其实是要爬完(越过)整个梯子才算到达顶部,相当于顶部是第len+1层台阶。台阶序号从0开始编号的话,顶部就是第len个台阶。2)从第i个台阶往上爬,才需要支付cost[i]。如果站在第i个台阶没有继续往上爬,则不需要支付const[i]。这样才好理解,dp[0]和dp[1]的值为什么是0。
第一版不带注释
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int len = cost.size();
if(len < 3) return min(cost[0],cost[1]);
vector<int> dp(len+1);
dp[0] = 0;
dp[1] = 0;
for(int i = 2;i <= len;i++){
dp[i] = min(cost[i-1]+dp[i-1],cost[i-2]+dp[i-2]);
}
return dp[len];
}
};
写完注释后,发现当len等于2的情形,其实不需要单独考虑,后面的代码可以涵盖这种情况。
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int len = cost.size();
//题目已经保证len>=2
// if(len < 3) return min(cost[0],cost[1]);
//给定的len层的梯子,楼顶其实是第len+1层
vector<int> dp(len+1);//dp[i]表示到达第i层台阶所需要的最低花费
dp[0] = 0;//含义是从第0层出发,爬0层就到达了第0层,不需要支付
dp[1] = 0;//含义是从第1层出发,爬0层就到达了第1层,不需要支付
//给定的len层的梯子,楼顶其实是第len+1层,但是由于从0开始编号,所以i应该取到len
for(int i = 2;i <= len;i++){
//到达第i层,有两种可能,要么是从第i-1层爬一个台阶到达的,
//要么是从第i-2层爬两个台阶到达的
dp[i] = min(cost[i-1]+dp[i-1],cost[i-2]+dp[i-2]);
}
return dp[len];
}
};
进一步优化空间开销。因为计算dp[i]只需要dp[i-1]和dp[i-2],所以可以去掉dp数组,改用两个变量,如代码所示:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int len = cost.size();
//题目保证len>=2,所以下面的i从2开始起算
int dp_i_2 = 0;//表示到达第i-2层所需的最小花费
int dp_i_1 = 0;//表示到达第i-1层所需的最小花费
int dp_i = 0; //表示到达第i层所需要的最小花费
for(int i = 2;i <= len;i++){
dp_i = min(dp_i_1+cost[i-1],dp_i_2+cost[i-2]);
dp_i_2 = dp_i_1;
dp_i_1 = dp_i;
}
return dp_i;
}
};