题目:
吐槽:1.首先作为一个动态规划的题目,我的解题方式都是先写递归版本的再改成非递归版本的,然而在网上别人的答案都直接是非递归版本,边界解释的也不清楚,最后自己一点点调试折腾了半天,感觉还是很有收获的。
2.这个题目代码虽然简单,看似是个水题,但是分的情况其实是很多的,在第一次A这种题的情况下想把代码写的很精炼我觉得难度还是很大的,所以我把各种情况的判断,分解出来。
代码:
递归版本
int[] result;
public int minCostClimbingStairs(int[] cost) {
//解题的前提:人是站在-1位置上的(相对于cost来说的)
//1.在没进入递归前的特例处理,当台阶数小于等于1的时候,直接返回0,因为可以不消耗体力直接迈过去。
if(cost.length<=1){
return 0;
}
//2.在没进入递归前的特例处理,当台阶数等于2的时候,从-1无法直接迈过去,所以在两个台阶上选择最小的那个作为返回值。
if(cost.length ==2){
return Math.min(cost[0],cost[1]);
}
//3.进入递归的算法逻辑,当cost.length的长度大于2的时候(台阶数大于2的时候),0和1号台阶必然会被踩一个。
//result数组表示,踩在第i个台阶上,所消耗的最少体力。
result = new int[cost.length+1];
//计算出踩在第i个台阶上所消耗的最少的能量的数组。
getresult(cost,cost.length);
// for(int i = 0;i<result.length;i++){
// System.out.println(result[i]);
// }
// System.out.print("================");
//cost.length处的台阶其实是不消耗体力的,因为没有cost[cost.length]这个值。result[cost.length-1]和
// result[cost.length-2]是两个我们需要的走路结果,因为再走1步或者2步就是无消耗到达cost.length台阶所消耗的能量。
return Math.min(result[cost.length-1],result[cost.length-2]);
}
private int getresult(int[] cost,int count) {
//当count>2的时候,必然会踩到cost[0]和cost[1]上,这两个返回值是递归的终止条件
if(count == 0){
return cost[0];
}
if(count == 1){
return cost[1];
}
//记忆化搜索的数组,当没有计算过的值,让其保存在数组里。
if(result[count] == 0){
//当计算result[cost.length]的时候因为cost[cost.length]值不存在需要特殊处理cost[cost.length] == 0
if(count == cost.length){
result[count] = getresult(cost,count-2)+0>getresult(cost,count-1)+0?
getresult(cost,count-1)+cost[count-1]:getresult(cost,count-2)+cost[count-1];
}else{
//走两步到达count台阶所消耗的能量
int a =getresult(cost,count-2)+cost[count];
//走一步到达count台阶所消耗的能量
int b = getresult(cost,count-1)+cost[count];
//选择消耗最少的值保存在数组。
result[count] = a>b? b:a;
}
}
return result[count];
}
动态规划版本
int[] result;
public static int minCostClimbingStairs(int[] cost) {
//解题的前提:人是站在-1位置上的(相对于cost来说的),result[i]表示(i>2)踩在第i个台阶上所消耗的最少体力。
//1.cost.length长度小于等于2的情况特殊处理
if(cost.length<=1){
return 0;
}
if(cost.length ==2){
return Math.min(cost[0],cost[1]);
}
//2.动态规划初始条件填写。
result = new int[cost.length];
result[0] = cost[0];
result[1] = cost[1];
//3.计算到第i个台阶消耗最少能体力的数组。
for(int i = 2;i<cost.length;i++){
result[i] = Math.min(result[i-1]+cost[i],result[i-2]+cost[i]);
}
//4.只需要返回result[cost.length-1],result[cost.length-2]的最小值就好,因为
//result[cost.length-1]是走到cost.length-1位置所消耗的最少体力,cost走到最后了。
//result[cost.length-2]是走到cost.length-2位置所消耗的最少体力,可以走两步不消耗能量。
return Math.min(result[cost.length-1],result[cost.length-2]);
}