LeetCode每日一题 | 746.使用最小花费爬楼梯

题目链接:

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

题目描述:

题目图解:

思路解析:

这是一个连续的中间态不断推导的问题,即到达每一层所花费的费用都依赖于上一层和上上一层

我们创建一个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 ] );

 有了状态转移方程以后我们就可以开始着手解题了:

  1. 首先我们创建dp表,因为终点是在cost表末尾的下一个位置,因此dp表的大小应该是cost表的大小加一
  2. 其次我们要对一些已有的数据进行初始化,同时判断边界问题,因为到达第0层和第1层的花费都是0,所以dp表中0号位置和1号位置我们都填入0,其次根据状态转移方程为了不越界访问,i的值必须大于2小于cost.size()
  3. 完成上面两步我们就可以进行填表了
  4. 最后返回我们要求的结果

解题代码:

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];//返回结果
    }
};

总结:

对于这种下一步结果依赖上一步结果的题目,根据不断的递推来求解的问题,我们可以根据中间态找出它的状态转移方程,然后从原点开始先进行初始化然后根据条件进行一步接一步的递推关系求解。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值