题目链接:
题目描述:
题目图解:
思路解析:
这是一个连续的中间态不断推导的问题,即到达每一层所花费的费用都依赖于上一层和上上一层
我们创建一个dp表(线性表)用来表示到达每一层的最小花费
1.我们从原点开始推导:
next
next
我们发现到达第 i 层时,只有两种方法,要么从第 i - 1 层花费第 i - 1 层的过路费走一步到达第 i 步,要么从第 i - 2 层花费第 i - 2 层的过路费走两步到达第 i 层,而这两种方式中花费费用最少的就是到达第 i 层的费用。
根据上面我们找到的关系可以列出状态转移方程:
dp[ i ] = min ( dp[ i − 1 ] + cost[ i − 1 ], dp[ i − 2 ] + cost[ i − 2 ] );
有了状态转移方程以后我们就可以开始着手解题了:
- 首先我们创建dp表,因为终点是在cost表末尾的下一个位置,因此dp表的大小应该是cost表的大小加一
- 其次我们要对一些已有的数据进行初始化,同时判断边界问题,因为到达第0层和第1层的花费都是0,所以dp表中0号位置和1号位置我们都填入0,其次根据状态转移方程为了不越界访问,i的值必须大于2小于cost.size()
- 完成上面两步我们就可以进行填表了
- 最后返回我们要求的结果
解题代码:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
vector<int> dp(n + 1);//创建dp表
dp[0] = dp[1] = 0;//初始化dp表
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];//返回结果
}
};
性能优化:
上述代码的时间复杂度和空间复杂度都是 O(n)。注意到当 i ≥ 2 时,dp[ i ] 只和 dp[ i − 1] 与 dp[ i − 2 ]有关,因此可以使用滚动数组的思想,将空间复杂度优化到 O(1)。
我们不必再创建大小为 cost.size() + 1 大小的dp表,而是通过大小为3的dp滚动数组进行求解
代码如下:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
vector<int> dp(3);//创建滚动数组
dp[0] = dp[1] = 0;//初始化dp滚动数组
for(int i = 0; i <= n-2 ; i++)
{
//滚动
dp[2] = min(dp[0]+cost[i],dp[1]+cost[i+1]);
dp[0]=dp[1];
dp[1]=dp[2];
}
return dp[2];//返回结果
}
};
总结:
对于这种下一步结果依赖上一步结果的题目,根据不断的递推来求解的问题,我们可以根据中间态找出它的状态转移方程,然后从原点开始先进行初始化然后根据条件进行一步接一步的递推关系求解。