题目
使用最小花费爬楼梯
给你一个整数数组 cost
,其中 cost[i]
是从楼梯第 i
个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0
或下标为 1
的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1:
输入: cost = [10,15,20] 输出: 15 解释: 你将从下标为 1 的台阶开始。 - 支付 15 ,向上爬两个台阶,到达楼梯顶部。 总花费为 15 。
示例 2:
输入: cost = [1,100,1,1,1,100,1,1,100,1] 输出: 6 解释: 你将从下标为 0 的台阶开始。 - 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。 - 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。 - 支付 1 ,向上爬一个台阶,到达楼梯顶部。 总花费为 6 。
提示:
2 <= cost.length <= 1000
0 <= cost[i] <= 999
题解
解题分析
题解思路
- 该题是一个典型的动态规划题目;
- 假设数据的长度为 n , 则 n 个阶梯非别对应数组下标 0 到 n-1, 楼层顶部对应下标 n, 问题等于达到 n 的最小花费。
- 创建一个长度为 n+1 长度的数组 dp, 其中 dp[i] 表示达到下标 i 的最小花费。由于可以选择 0 或者 1 作为初始阶梯,因此有
dp[0] = dp[1] = 0
。
- 当
2 <= i <= n
时,可以从下标i-1
使用cost[i-1]
的花费达到下标 i, 或者从下标 i -2 使用的花费到达下标 i。为了使总花费最小, dp[i] 应该取上述两项的最小值,因此状态转移方程如下:
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i -2])
依次计算 dp 中的每一项的值,最终得到的 dp[n] 即为达到楼层顶部的最小花费。
class Solution { public int minCostClimbingStairs(int[] cost) { int n = cost.length; int[] dp = new int[n + 1]; dp[0] = dp[1] = 0; for (int i=2; i <=n; i++) { dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]); } return dp[n]; } }
上述的代码时间复杂读度和空间复杂度都是 O(n)。注意当 i>= 的时候,只与 dp[i -1]
和 dp[i-2]
有关,因此可以使用滚动数组的思想优化空间复杂度到 O(1).具体代码如解题代码所示。
复杂度分析
- 时间复杂度:O(N)
- 空间复杂度:O(1)
解题代码
题解代码如下(代码中有详细的注释说明):
class Solution { public int minCostClimbingStairs(int[] cost) { int n = cost.length; // dp[0], dp[1] int prev = 0, curr = 0; for (int i=2; i<= n; i++) { int next = Math.min(curr + cost[i-1], prev + cost[i-2]); prev = curr; curr = next; } return curr; } }
提交后反馈结果: