算法
概:这波啊,好久没更博客了,今天这个每日一题有点好玩(纪念自己能想出来简单动态规划。
来源:力扣(LeetCode)
链接:使用最小花费爬楼梯
题目
- 原题:
数组的每个索引作为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i] (索引从0开始)。
每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。
您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。 - 个人补充:
讲实话 这道题感觉题目语言组织的不太好,刚开始没太看懂,大概就是让你爬个楼梯,然后你可以选择从第0级开始或者从第1级开始爬,但是注意了,规则很离谱,不是说每个台阶你都得过,你可以选择跳过面前的那个台阶直接抵达下一个,并且不消耗面前那个台阶需要的体力(想不到吧)。当你从第i个台阶向前走,你可以选择走到i+1个台阶或者走到i+2个台阶,并且消耗的体力均为cost[i]。
示例
示例 1:
输入: cost = [10, 15, 20]
输出: 15
解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。
示例 2:
输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出: 6
解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。
注意:
cost 的长度将会在 [2, 1000]。
每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]。
思路
- 上去啪一下就想到贪心了,很快啊! 然后发现打错了,该打动态规划的。你们可能不知道,只遍历一遍数据就得出多种路径最优结果是个什么概念,我们一般只会用一个名字来叫这种方法,动态规划(玩梗,别打)
具体思路:
- 我们可以计算一个dp数组,每个节点对应你从开头开始走到走过当前节点所需要的所有体力的最优解。0号节点,其可以作为初始节点,所以其体力消耗最小值就是它本身的消耗cost[0],1号节点和0号节点同理,为cost[1]
- 然后看后面的节点,到达节点i之前,可以是从i-1走一位消耗最少dp[i-1]到达节点i,也可以是从i-2位走俩位消耗最少dp[i-2]到达节点i。所以到达i节点最少消耗就是 dp[i-1]+cost[i] 和 dp[i-2]+cost[i] 俩个之中最小的.即能得出dp[i] = min(dp[i-1]+cost[i],dp[i-2]+cost[i]);
- 这样我们就可以直接计算出dp数组,来知道经过每一个节点的最少消耗。要到达顶层(数组之外)。可以是最后一级走一步或者倒数第二级走俩步。即,挑选dp数组最后俩个元素中小的那个一个。
- 优化:如上三点所述,我们计算的时候只需要遍历一次cost数组,而已经遍历过的元素没有任何作用,我们所需要的仅仅是当前遍历的cost[i]和已经算到的dp[i-1]和dp[i-2].也正因此,我们可以直接将dp的结果存进cost数组中,节省空间。
c++代码
class Solution
{
public:
int minCostClimbingStairs(vector<int>& cost) {
for (int i = 2; i < cost.size(); i++)
{
if (cost[i - 1] < cost[i - 2])
{
cost[i] += cost[i - 1];
}
else
{
cost[i] += cost[i - 2];
}
}
if (cost[cost.size() - 1] < cost[cost.size() - 2])
{
return cost[cost.size() - 1];
}
else
{
return cost[cost.size() - 2];
}
}
};