题目描述

image.png

解题思路

普通写法

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

使用动态规划,就要有一个数组来记录状态,本题只需要一个一维数组dp[i]就可以了。
dp[i]的定义:到达第i个台阶所花费的最少体力为dp[i]。(注意这里认为是第一步一定是要花费)

  • 确定递推公式

可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]
那么究竟是选dp[i-1]还是dp[i-2]呢?
一定是选最小的,所以dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i];
也就是选出前一个阶梯或者前两个最小的体力,在加上跳到本次的体力。

  • dp数组如何初始化

那么只初始化dp[0]和dp[1]就够了。

  • 遍历顺序

从前向后

  • 打印dp数组

    1. public int minCostClimbingStairs(int[] cost) {
    2. // dp[i] 表示到达i层所花费的最小的体力值,认为第一步也花费体力值
    3. int[] dp = new int[cost.length];
    4. // 初始化dp数组,低0层和第1层所花费的体力值,而最后一层不需要花费体力值
    5. dp[0] = cost[0];
    6. dp[1] = cost[1];
    7. for (int i = 2; i < cost.length; i++) {
    8. dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]; // 最小的体力值和花费跳到当前楼梯的体力值
    9. }
    10. return Math.min(dp[cost.length - 1], dp[cost.length - 2]);
    11. }

优化

  1. public int minCostClimbingStairs(int[] cost) {
  2. int dp0 = cost[0];
  3. int dp1 = cost[1];
  4. for (int i = 2; i < cost.size(); i++) {
  5. int dpi = min(dp0, dp1) + cost[i];
  6. dp0 = dp1; // 记录一下前两位
  7. dp1 = dpi;
  8. }
  9. return min(dp0, dp1);
  10. }

另一种写法

从题目描述可以看出:要不是第一步不需要花费体力,要不就是第最后一步不需要花费体力,我个人理解:题意说的其实是第一步是要支付费用的!。因为是当你爬上一个台阶就要花费对应的体力值!
所以我定义的dp[i]意思是也是第一步是要花费体力的,最后一步不用花费体力了,因为已经支付了。
当然也可以样,定义dp[i]为:第一步是不花费体力,最后一步是花费体力的。

  1. public int minCostClimbingStairs(int[] cost) {
  2. int[] dp = new int[cost.length + 1];
  3. // 默认第一步不花费体力,而最后一步花费体力
  4. dp[0] = 0;
  5. dp[1] = 0;
  6. for (int i = 2; i <= cost.length; i++) {
  7. dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
  8. }
  9. return dp[cost.length];
  10. }