748.使用最小花费爬楼梯
给你一个整数数组 cost
,其中 cost[i]
是从楼梯第 i
个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0
或下标为 1
的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例
输入: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 。
方法一:动态规划
本文介绍的解法和力扣官方题解的方法思路一致,只是本文中dp数组的定义有所不同,进而dp数组的初始化、递推公式、遍历顺序都有所不同。
按照中动态规划专题介绍的动态规划5步法来求解:
-
确定dp数组以及下标的含义
使用动态规划需要记录状态信息,根据题意,可以设置一个一维数组dp[i]来记录从第i层爬到阶梯顶的最低费用。
-
确定递推公式
依据题意,当支付了第i层的费用 cost[i] 之后,可以选择向上爬一个或两个台阶,所以从第i层爬到阶梯顶的费用 等于 cost[i] + dp[i+1],或等于 cost[i] + dp[i+2]。
所以
dp[i] = cost[i] + min( dp[i+1], dp[i+2])
。 -
dp数组如何初始化
依据题意,从第cost.size-1层爬到阶梯顶的最低费用为 cost[size-1];
从第cost.size-2层爬到阶梯顶的最低费用为 cost[size-2];
vector<int> dp(cost.size()); dp[size-1] = cost[size-1]; dp[size-2] = cost[size-2];
-
确定遍历顺序
由递推公式可以看出,需要从后往前遍历。
-
举例推导dp数组
拿示例:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] ,来模拟⼀下dp数组的状态变化,如下:
下标i 0 1 2 3 4 5 6 7 8 9 dp[i] 6 105 5 5 4 102 3 2 100 1 通过dp[0]、dp[1]的最小值判断从下标为0或下标为1的台阶开始爬楼梯。
代码实现
int minCostclimbingStairs(vector<int>& cost) {
int size = cost.size();
vector<int> dp(size);
dp[size - 1] = cost[size - 1];
dp[size - 2] = cost[size - 2];
for (int i = size - 3; i >= 0; i--) {
dp[i] = cost[i] + min(dp[i + 1], dp[i + 2]);
}
return min(dp[0], dp[1]);
}
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
还可以优化空间复杂度,因为dp[i]通过后两位推导出来的,最终只需要比较dp[0]和dp[1],所以只需要维护两个元素即可
int minCostclimbingStairs2(vector<int>& cost) {
int size = cost.size();
vector<int> dp(2);
dp[1] = cost[size - 1];
dp[0] = cost[size - 2];
for (int i = size - 3; i >= 0; i--) {
int sum = cost[i] + min(dp[0], dp[1]);
dp[1] = dp[0];
dp[0] = sum;
}
return min(dp[0], dp[1]);
}
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
原文地址:https://www.jb51.cc/wenti/3282972.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。