详细图解动态规划leetcode_746. 使用最小花费爬楼梯--简单动态规划

问题描述

数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。

每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。

请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 01 的元素作为初始阶梯。

示例 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]);

	    }
	}

在这里插入图片描述

总结

  1. dp数组的每一个值实际上是起点到当前阶梯的最小花费
  2. dp思想实际上是将大问题转化为****一个个的小问题
  3. 在本题中,每个小问题是如果想要求得从起点到当前阶梯的最小花费,那么就要找到可以到当前阶梯的前两个阶梯最小花费最小值
  4. 本题中状态转移方程为:dp[i]=Math.min(dp[i-1], dp[i-2])+dp[i]
  5. 本题中的时间复杂度为O(N);空间复杂度是O(N);

写在最后

如果感觉写的还不错的话不妨分享给其他人,以求共同进步

文章如有错误之处请指出,我会听取并改正

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值