题目

给定一个整数数组 cost,其中 cost[i] 是从楼梯第i个台阶向上爬需要支付的费用,下标从0开始。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

数据范围:数组长度满足1≤n≤10^5  ,数组中的值满足1≤costi​≤10^4。

示例1

输入:[2,5,20]

返回值:5

说明:你将从下标为1的台阶开始,支付5 ,向上爬两个台阶,到达楼梯顶部。总花费为5。

示例2

输入:[1,100,1,1,1,90,1,1,80,1]

返回值:6

说明:你将从下标为 0 的台阶开始。

  1. 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
  2. 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
  3. 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
  4. 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
  5. 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
  6. 支付 1 ,向上爬一个台阶,到达楼梯顶部。

总花费为6。


思路:动态规划

动态规划,英文:Dynamic Programming,简称DP。如果某一问题有很多重叠子问题,使用动态规划是最有效的。

动态规划算法的基本思想是:

  • 将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
  • 对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。
  • 动态规划算法将问题的解决方案视为一系列决策的结果。
  • 所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。

动态规划的解题步骤:

  1. 确定dp数组(dp table)以及下标的含义。
  2. 确定递推公式。
  3. dp数组如何初始化。
  4. 确定遍历顺序。
  5. 举例推导dp数组。

为什么要先确定递推公式,然后在考虑初始化呢?——因为一些情况是递推公式决定了dp数组要如何初始化!

题目中说 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯” 也就是相当于直接跳到下标 0 或者直接跳到下标 1 是不花费体力的, 从下标 0 跳到下标1 开始跳就要花费体力了。

  • step1:确定dp数组以及下标的含义。

使用动态规划,就要有一个数组来记录状态,本题只需要一个一维数组dp[i]就可以了。

dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]

  • step2:确定递推公式。

可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]

dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。

dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。

那么究竟是选从dp[i - 1]跳还是从dp[i - 2]跳呢?

一定是选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);

  • step3:dp数组如何初始化?

看一下递归公式,dp[i]由dp[i - 1], dp[i - 2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0],dp[1]推出。

那么 dp[0] 应该是多少呢? 根据dp数组的定义,到达第0台阶所花费的最小体力为dp[0],那dp[0] 应该是 cost[0],例如 cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 的话,dp[0] 就是 cost[0] 应该是1。

但注意题目描述中明确说了 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。” 也就是说从到达第 0 个台阶是不花费的,但从第0个台阶往上跳的话,需要花费 cost[0]。

所以初始化 dp[0] = 0,dp[1] = 0。

  • step4:确定遍历顺序。

最后一步,递归公式有了,初始化有了,如何遍历呢?本题的遍历顺序其实比较简单。

因为是模拟台阶,而且dp[i]由dp[i-1],dp[i-2]推出,所以是从前到后遍历cost数组就可以了。

但是稍稍有点难度的动态规划,其遍历顺序并不容易确定下来

例如:0-1背包,都知道两个for循环,一个for遍历物品嵌套一个for遍历背包容量,那么为什么不是一个for遍历背包容量嵌套一个for遍历物品呢? 以及在使用一维dp数组的时候遍历背包容量为什么要倒序呢?这些都与遍历顺序息息相关。

  • step5:举例推导dp数组。

拿cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 来模拟一下dp数组的状态变化,如下:


代码1

// 方式一:第一步不支付费用
class Solution {public int minCostClimbingStairs(int[] cost) {int len = cost.length;int[] dp = new int[len + 1];// 从下标为 0 或下标为 1 的台阶开始,因此支付费用为0dp[0] = 0;dp[1] = 0;// 计算到达每一层台阶的最小费用for (int i = 2; i <= len; i++) {dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[len];}
}

代码2

// 方式二:第一步支付费用
class Solution {public int minCostClimbingStairs(int[] cost) {int[] dp = new int[cost.length];dp[0] = cost[0];dp[1] = cost[1];for (int i = 2; i < cost.length; i++) {dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i];}//最后一步,如果是由倒数第二步爬,则最后一步的体力花费可以不用算return Math.min(dp[cost.length - 1], dp[cost.length - 2]);}
}

BM64-最小花费爬楼梯相关推荐

  1. LeetCode-动态规划基础题-746. 使用最小花费爬楼梯

    描述 746.使用最小花费爬楼梯 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始). 每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应 ...

  2. LeetCode Algorithm 746. 使用最小花费爬楼梯

    746. 使用最小花费爬楼梯 Ideas 首先确定题目类型,爬楼梯问题,并且给定了状态转移的限制,其实就已经可以确定状态转移方程了. 然后题目说可以从下标为0或下标为1的台阶开始爬,所以我们可以定义两 ...

  3. 算法题目——使用最小花费爬楼梯(动态规划)

    题目链接:746.使用最小花费爬楼梯 方法:动态规划 假设数组cost的长度为n,则n个阶梯分别对应下标0到n- 1,楼层顶部对应下标n,问题等价于计算达到下标n的最小花费.可以通过动态规划求解. 创 ...

  4. 746. 使用最小花费爬楼梯 golang 动态规划

    746. 使用最小花费爬楼梯 746. 使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 costi. 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以 ...

  5. leetcode - 746. 使用最小花费爬楼梯

    746. 使用最小花费爬楼梯 -------------------------------------- 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i] (索引 ...

  6. 动态规划——使用最小花费爬楼梯(Leetcode 746)

    题目选自Leetcode 746.使用最小花费爬楼梯 题目描述: 解题代码:C语言 int minCostClimbingStairs(int* cost, int costSize) {int pr ...

  7. 746.使用最小花费爬楼梯

    使用最小花费爬楼梯 方法一: class Solution {public int minCostClimbingStairs(int[] cost) {if (cost == null || cos ...

  8. D38| DP理论基础 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

    DP理论基础 重要知识点: 1.动规和贪心的区别:动规是由前一个状态推导出来的,而贪心是局部直接选最优的 2.动规五部曲: 1)确定dp数组(dp table)以及下标的含义 2)确定递推公式 3)d ...

  9. [每日一题]746. 使用最小花费爬楼梯

    [每日一题]746. 使用最小花费爬楼梯 数组的每个索引作为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 costi. 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯 ...

  10. Java实现 LeetCode 746 使用最小花费爬楼梯(递推)

    746. 使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 costi. 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶 ...

最新文章

  1. 借助队列解决Josephus问题
  2. EMetaBlob类分析
  3. android toolbar 开发总结
  4. 浅析移动端网站是如何做好前期策划工作的?
  5. 《C语言课程设计》一3.1 文件复制
  6. Python uuid 介绍
  7. java表格树_Java程序员值得拥有的TreeMap指南
  8. cfree是c语言程序的什么,用C-FREE编写的C语言程序
  9. 异星工厂 自动机器人_刚刚,ABB机器人全球最大机器人超级工厂在康桥动工! 投资10亿元,用机器人造机器人...
  10. Halcon求取矩形顶点坐标
  11. java访问错误404_如何解决 Java web 项目中的 404 错误
  12. 登顶Github趋势榜,非监督GAN算法U-GAT-IT大幅改进图像转换效果
  13. 代码chaid_适配者 – 研究和分享IT前沿技术,形成以开源软件、代码分享、技术分享、IT职业发展等经验分享网站。...
  14. “滚!”央视、腾讯暂停NBA季前赛转播,NBA被中国市场“下架”!
  15. php任务奖励体系,phpwind7.5完备的积分体系
  16. ES6模块的循环加载
  17. [UI]抽屉菜单DrawerLayout分析(三)
  18. java基础知识---IO常用基础操作(二)
  19. 其它——Siege压力测试工具使用
  20. 自然语言处理5:jieba分词详解全模式,精确模式和搜索引擎模式

热门文章

  1. 研究生必备:从0到1使用Zotero
  2. PostgreSQL安装教程(Win10)
  3. 清华/阿里巴巴开源的周期型——Donut
  4. 搭建Vue3开发微信小程序
  5. ServiceComb/CSE常见问题处理(1812)
  6. uni-app使用阿里巴巴矢量图标库
  7. WooCommerce电子商务WordPress插件-赚美国人的钱
  8. python实现BPSK调制信号解调
  9. 计算机科学与技术领域主要免费网络资源数据库网址
  10. stm32蜂鸣器设置