ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-10-02使用最小花费爬楼梯错误思路和正确思路对比

2021-10-02 11:34:58  阅读:151  来源: 互联网

标签:02 10 int 花费 cost 思路 index1 index0 dp


题干

题目来源力扣

首先放入最后运行正确的答案

class Solution {
    public int minCostClimbingStairs(int[] cost) {
       //到达楼顶的最低花费 = Math.min(到达次一层的最低花费+次一层的花费值,到达次二层的最低花费)

       int[] dp = new int[cost.length];
       dp[0]=cost[0];
       dp[1]=cost[1];

       for(int i=2;i<cost.length;i++)
       {
           dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i];
       }

       return Math.min(dp[dp.length-1],dp[dp.length-2]); 
    }
}

从注释可以看出运用了动态规划的思维.从当前所站的位置去考虑最低花费,是一个逆推的过程。
动态规划方程为到达楼顶的最低花费 = Math.min(到达次一层的最低花费+次一层的花费值,到达次二层的最低花费)
边界值为下标0或者下标1

下面是一些错误解答

第一种

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] comsumption = new int[2];
        comsumption[0] = cost[0];
        comsumption[1] = cost[1];

        int index0 = 0;
        int index1 = 1;
        while(index0 < cost.length-2)
        {
            comsumption[0] += cost[index0+1]>=cost[index0+2]?cost[index0+2]:cost[index0+1];
            if(cost[index0+1]>=cost[index0+2])
            {
                index0 = index0+2;
            }
            else
            {
                index0 = index0+1;
            }
        }

        while(index1 < cost.length-2)
        {
            comsumption[1] += cost[index1+1]>=cost[index1+2]?cost[index1+2]:cost[index1+1];
            if(cost[index1+1]>=cost[index1+2])
            {
                index1 = index1+2;
            }
            else
            {
                index1 = index1+1;
            }
        }

        return Math.min(comsumption[0],comsumption[1]);
        
    }
}

因为只涉及到了当前楼层,次级楼层和次次级楼层,所以设想使用滚动数组comsumption来存储次级楼层和次次级楼层的最低花费。因为题干中明确指出可以选择下标初始值为0或者1,因此我设计将其分为两种不同情况分开进行。下面以下标为0作为例子来描述我的设计思路。

while(index0 < cost.length-2)
        {
            comsumption[0] += cost[index0+1]>=cost[index0+2]?cost[index0+2]:cost[index0+1];
            if(cost[index0+1]>=cost[index0+2])
            {
                index0 = index0+2;
            }
            else
            {
                index0 = index0+1;
            }
        }

这部分代码可以看出与运行成功的代码的最大不同就是指针的含义不同。上述代码中指针是站在已经花费体力的台阶上计算下一步要如何选择才能达到最低花费(1),而运行成功代码的指针则是站在还未花费体力的台阶上回顾来路去思考如何能花费最低(2)。这点似乎就是一开始无法解决这道题的最为致命的地方。因为想方法(1)这样去设计每一步选择只能是当前最优解,而方法(2)这种做法才能实现达到目标的最优解。
使用方法(1)无法通过的情况如下:
测试用例1
最低花费应当是2,但是按照方法(1)得出的最优解为3,流程为0->1->2。

在看了一些评论之后我修改了我自己的想法,写下新的错误解答。

第二种

class Solution {
    public int minCostClimbingStairs(int[] cost) {
       int index =  cost.length;
       int value = 0;

       while(index >= 2)
       {
           value += cost[index-1]<cost[index-2]?cost[index-1]:cost[index-2];
           if(cost[index-1]<cost[index-2])
           {
               index = index-1;
           }
           else
           {
               index = index-2;
           }
       }
        
        return value;
    }
}

上述代码则是使用了逆推的形式,假设我现在处在楼顶回顾来路去计算最低花费,但这仍旧是一个错误答案。
在这里插入图片描述

使用第二种错误做法来解答上图的测试用例,流程如下:
顶层->1>下标为1的2
正确做法,流程如下:
dp[2]=2->dp[3]=3->顶层dp=2

下面来分析两个方法的不同:
正确做法的下标是规律递增,最低花费确实是动态变化的;第二种错误做法则是下标和最低花费同步运动。这是因为得出最后结果需要对来路每一步都进行判断,从而选出最低花费,而错误做法仍是在做对当前最优解的累加,只不过是换了个方向。

通过对上述的分析 动态规划需要遍历每一步判断从而得出结果 同时最终结果需要和之前的结果有关联。

更新与滚动数组相结合的解法 空间复杂度为常数值

class Solution {
    public int minCostClimbingStairs(int[] cost) {
       //到达楼顶的最低花费 = Math.min(到达次一层的最低花费+次一层的花费值,到达次二层的最低花费)

       //int[] dp = new int[cost.length];
       int[] dp = new int[2];
       dp[0]=cost[0];
       dp[1]=cost[1];

       for(int i=2;i<cost.length;i++)
       {
           //dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i];
           dp[i%2] = Math.min(dp[0],dp[1])+cost[i];
       }

       //return Math.min(dp[dp.length-1],dp[dp.length-2]);
       return Math.min(dp[0],dp[1]);  
    }
}

标签:02,10,int,花费,cost,思路,index1,index0,dp
来源: https://blog.csdn.net/nnxzdwbk_/article/details/120583927

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有