动态规划leetcode_746--简单
问题描述
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
示例 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] 将会是一个整型数据,范围为 [0, 999] 。
来源:力扣(LeetCode)
思路描述
拿到这道题看到关键字最低花费结合题意可以知道这道题应该是一道动态规划题,我对于动态规划一般有如下做法:
1. 使用最笨的方法暴力破解出来这一道题
2. 找到一定的规律
3. 寻找到状态转移方程
4. 由状态转移方程的形式继续寻找对应的dp数组
5. 从dp数组中找到我所求的值
下面我会从一道例题来解释以上操作
图解思路
首先我先设cost={101,100,1,1,1,100,1}
1. 使用最笨的方法暴力破解出来这一道题
不难看出这道题应该找的是红色的数值
那么这样的数值是怎么找到的呢
我们应该先设我们已经找到了几个数值,由这些数值就可以得到最少的体力花费
2. 找到一定的规律
接下来我们观察这个list的组成,会发现得到的每一个值都是在当前值的前面的值已经是最优确定的情况下,当前值才被选出来的
3. 寻找到状态转移方程
由以上规律不难看出状态转移方程为:dp[i]=Math.min(dp[i-1], dp[i-2])+dp[i]
4. 由状态转移方程的形式继续寻找对应的dp数组
由这样的规律可以创建出一个dp数组
这个dp数组的和原数组一摸一样,我们在这个dp数组中寻找最小的花费
由状态转移方程可以看出dp数组应执行以下操作:
1. 操作1:将可达阶梯上的值和当前站在地方的值相加放入数组中
2. 操作2:找到最小的可达阶梯上的值替换为当前阶梯,如果两个可达阶梯值相同,就选择离当前阶梯远的阶梯替换为当前阶梯
3. 循环操作2直到数组遍历完成
4. 返回最后两个值中的最小值
可以得到dp数组的变化形式为:
5. 从dp数组中找到我所求的值
由于最后两个阶梯都可以直接到达顶层因此dp数组的最后两个值的较小的那个值就是最终答案
注1:第一个0元素并不存在,只是为了便于理解dp数组的变化而添加
注2:所返回的dp数组中的每个值实际上就是到达这个台阶需要的最小花费
注3:最后两个值取得最小的是因为这两个值都可以直接跳到顶层
代码实现
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp=new int[cost.length];
//将原数组复制给dp数组
System.arraycopy(cost, 0, dp, 0, cost.length);
//从第二个值开始寻找最优解直到寻找结束
for(int i=2;i<dp.length;i++){
dp[i]+=Math.min(dp[i-1], dp[i-2]);
}
//找到最后两个值中的小值
return Math.min(dp[dp.length-1], dp[dp.length-2]);
}
}
总结
- dp数组的每一个值实际上是起点到当前阶梯的最小花费
- dp思想实际上是将大问题转化为****一个个的小问题
- 在本题中,每个小问题是如果想要求得从起点到当前阶梯的最小花费,那么就要找到可以到当前阶梯的前两个阶梯的最小花费的最小值
- 本题中状态转移方程为:dp[i]=Math.min(dp[i-1], dp[i-2])+dp[i]
- 本题中的时间复杂度为O(N);空间复杂度是O(N);
写在最后
如果感觉写的还不错的话不妨分享给其他人,以求共同进步!
文章如有错误之处请指出,我会听取并改正!