746使用最小花费爬楼梯
0. 题目描述
数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始)。
每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。
您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。
1. 样例数据
dp | 1 | 1 | 7 | 9 | 10 | 9 |
费用 | 1 | 1 | 6 | 8 | 3 | 0 |
下标 | 0 | 1 | 2 | 3 | 4 | 终点 |
2. 分析最优子结构
假设我们现在已经到达了楼顶nums[10],要想得到最小的消耗,那就需要在到达顶楼前的一步就是最小的消耗,到达楼顶前的一步一共有两种走法,
一个是走一步: 下标4到终点,另一种是走两步:下标3到终点
为得到最优解,我们需要比较这两个走法的最小值.
我们设opt(i)为当前到第i个台阶时的最优解(最小的消耗),到达楼顶时:opt(10) = min{ opt(3) , opt(4) }+nums(5)
3. 分析边界
题目已经告诉我们,第一步可以选择第一阶或者第二阶,所以程序的边界就是opt(0) = nums(0), opt(1) = nums(1)
4. 递归,超时
//1. 递归做法,超时 func Min(i,j int)int{ if i < j { return i } return j } func helper(cost []int,count int) int{ if count == 0 || count ==1{ return cost[count] } sum := Min(helper(cost,count-1),helper(cost,count-2)) + cost[count] return sum } func minCostClimbingStairs(cost []int) int { return Min(helper(cost,len(cost)-1),helper(cost,len(cost)-2)) }
5. 动态规划
/** 1,1,6,8,3,0 下标:0,1,2,3,4,5终点 到达下标 0 ,需要最小花费1 到达下标 1 ,需要最小花费1 到达下标 2 ,需要最小花费Min(1+6,1+6) = 7 到达下标 3 ,需要最小花费MIn(1+8,7+8) = 9 到达下标 4 ,需要最小花费Min(7+3,9+3) = 10 到达下标 5 ,需要最小花费Min(9+0,10+0) = 9 */ func minCostClimbingStairs2(cost []int)int{ if len(cost) == 1{ return cost[0] }else if len(cost) == 2{ return Min(cost[0],cost[1]) } opt1 := cost[0] opt2 := cost[1] i := 2 for i <= len(cost){ if len(cost) == i { return Min(opt1,opt2) }else{ temp := Min(opt1+cost[i],opt2+cost[i]) opt1 = opt2 opt2 = temp } } return opt1 }