746. Min Cost Climbing Stairs* (使用最小花费爬楼梯)
https://leetcode.com/problems/min-cost-climbing-stairs/
题目描述
You are given an integer array cost
where cost[i]
is the cost of i
th step on a staircase. Once you pay the cost, you can either climb one or two steps.
You can either start from the step with index 0
, or the step with index 1
.
Return the minimum cost to reach the top of the floor.
Example 1:
Input: cost = [10,15,20]
Output: 15
Explanation: Cheapest is: start on cost[1], pay that cost, and go to the top.
Example 2:
Input: cost = [1,100,1,1,1,100,1,1,100,1]
Output: 6
Explanation: Cheapest is: start on cost[0], and only step on 1s, skipping cost[3].
Constraints:
2 <= cost.length <= 1000
0 <= cost[i] <= 999
代码实现
我觉得这道题有意思的地方在于, 每次去写它总认为自己会写错. 今天才明白, 之所以会产生这样的想法, 是因为我之前并没有将求解方法纳入现有的思考体系中. 之前在 746. Min Cost Climbing Stairs* 写的状态方程虽然简洁, 但感觉不符合我现在的思考方式.
本题采用动态规划求解, 使用 dp[i]
表示达到 i
时所需要付出的最小代价. 假设 cost
数组的大小为 N
, 最终的目标就是跳到第 N
个位置上, 所付出的代价就是 dp[N]
. 根据题意, 当你位于第 i
个位置时, 付出当前位置的花费 cost[i]
, 就可以跳一步或者两步. 那么要跳到第 i
个位置上时, 要么一开始就位于第 i - 1
的位置上, 然后付出 cost[i - 1]
的代价跳一步到达第 i
个位置; 要么一开始位于第 i - 2
的位置上, 然后付出 cost[i - 2]
的代价跳两步到达第 i
个位置;
综上, 状态转移方程呼之欲出:
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
要确定初始状态, 题目中说可以从第 0
个位置和第 1
个位置开始起跳, 那么:
dp[0] = 0;
dp[1] = 0;
再次注意 dp[i]
的含义是到达 i
时所需要付出的最小代价, 该位置上的花费 cost[i]
指的是你要离开 第 i
个位置时需要付出的代价, 由于我们可以直接从第 0
个位置和第 1
个位置开始起跳, 所以它们的初始值均设置为 0
. 最后我们只需要返回 dp[N]
就可以求解, 代码如下:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int N = cost.size();
vector<int> dp(N + 1, 0);
for (int i = 2; i <= N; ++ i)
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
return dp[N];
}
};
注意题目中说了数组的大小至少为 2
, 所以 N < 2
的情况不用考虑. 写到这, 代码还不算完, 还需要考虑能否进一步优化. 观察到 dp[i]
的结果只和 dp[i - 1]
和 dp[i - 2]
有关, 似乎不需要使用 vector
来记录所有历史结果, 只需要使用变量 dp0 = dp[i - 2], dp1 = dp[i - 1]
来保留历史状态, 同时不断维护 dp0
和 dp1
的状态.
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int N = cost.size();
int dp0 = 0, dp1 = 0, dp2 = 0;
for (int i = 2; i <= N; ++ i) {
dp2 = min(dp1 + cost[i - 1], dp0 + cost[i - 2]);
dp0 = dp1;
dp1 = dp2;
}
return dp2;
}
};
另外可以看看下面 “类似的题”, 均采用相同的思路就可以求解.