746.爬楼梯最小花费
力扣链接:746. 使用最小花费爬楼梯 - 力扣(Leetcode)
题目:
给你一个整数数组 cost
,其中 cost[i]
是从楼梯第 i
个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0
或下标为 1
的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
提示:
-
2 <= cost.length <= 1000
-
0 <= cost[i] <= 999
思路:
由此题变换而来力扣链接:70. 爬楼梯 - 力扣(Leetcode)
因此依旧考虑使用动态规划
首先分析题目,cost[i]表示的从i个台阶向上爬需要支付的费用,因此如果只是爬到第i个台阶,是不需要支付cost[i]的费用的,并且爬台阶限制在一次行动只能爬上一个或者两个台阶。
其次,2<=cost.length<=1000 表示不需要考虑 0,1的情况,省去了一些麻烦。
以 cost = [10,15,20] 为例,容易看出,楼顶是3。假设到达三楼的最小费用是profit[3],基于一次行动只能走一个台阶或者两个台阶的限制条件,不难推出到达三楼的最小费用由到达二楼的最小费用+cost[2]以及到达一楼的最小费用+cost[1]中的最小那个值决定。
即 profit[3] = min(profit[2]+cost[2],profit[1]+cost[1])
可能有人会疑惑为什么加cost,这是因为上面提到了,cost[i]表示的从i个台阶向上爬需要支付的费用,如果只是爬到第i个台阶,是不需要支付cost[i]的费用的。
以 profit[3] 为例,其最小值为第二个台阶的最小值profit[2] 向上走一个台阶得到,而想从第二个台阶向上爬,需要支付cost[2]的费用。这就是为什么 profit[3] = profit[2] + cost[2];
同理,profit[n] = min(profit[n-1]+cost[n-1],profit[n-2]+cost[n-2])
因为profit[n]代表到达第n个台阶的最小值,因此profit数组的长度为cost数组长度+1
为了更易理解动态规划,代码将 profit 重命名为 dp。
代码
/** * 爬楼梯的最小花费 * @param cost cost[i]表示从i楼继续往上爬需要支付的费用 * @return 返回最小花费 */ public int minCostClimbingStairs(int[] cost) { /* cost = [10,15,20] dp[i]为爬到i楼最小的花费 状态转移方程 dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]) */ int len = cost.length; if(len == 1) return 0; if(len == 2) return Math.min(cost[0],cost[1]); int[] dp = new int[len+1]; dp[0] = 0; dp[1] = 0; for (int i = 2; i < len+1; i++) { int cost1 = dp[i-1]+cost[i-1]; int cost2 = dp[i-2]+cost[i-2]; dp[i] = Math.min(cost1,cost2); } return dp[len]; }