剑指Offer题目笔记26(动态规划的基础知识)

面试题88:

面试题88

问题:

​ 一个数组cost的所有数字都是正数,它的第i个数字表示在一个楼梯的第i级台阶往上爬的成本,在支付了成本cost[i]之后可以从第i级台阶往上爬1级或2级。请计算爬上该楼梯的最少成本。

解决方案一:(递归:力扣超时)

解决方案:

​ 从第i级台阶往上爬的最少成本应该是从第i-1级台阶往上爬的最少成本和从第i-2级台阶往上爬的最少成本的较小值再加上爬第i级台阶的成本。故该关系的状态转移方程为dp(i) = min(dp(i-1),dp(i-2)) + cost[i]。

源代码:
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int len = cost.length;
        return Math.min(dfs(cost,len-1),dfs(cost,len-2));
    }

    private int dfs(int[] cost,int len){
        if(len < 2){
            return cost[len];        
        }
        return Math.min(dfs(cost,len-1),dfs(cost,len-2)) + cost[len];
    }
}

解决方案二:(使用缓存的递归)

解决方案:

​ 不使用缓存的话,需要反复计算前一个递归。例如求f(9)就需要先求f(8)和f(7),而计算f(8)就需要计算f(7)和f(6),以此类推,需要重复计算的数据量太大、时间复杂度很高。故为了避免重复计算带来的问题,一个常用的解决办法是将已经求解过的问题的结果保存下来。在每次求解一个问题之前,应先检查该问题的求解结果是否已经存在。如果问题的求解结果已经存在,则不再重复计算,只需要从缓存中读取之前求解的结果。

源代码:
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int len = cost.length;
        int[] dp = new int[len];
        dfs(cost,dp,len-1);
        //dfs(cost,dp,len-2);这条代码是我加上去的,不然跑不过样例:[1,100],加了还是超时,力扣还差两个样例跑不过。
        dfs(cost,dp,len-2);
        return Math.min(dp[len-1],dp[len-2]);
    }

    private void dfs(int[] cost,int[] dp,int len){
        if(len < 2){
            dp[len] = cost[len];
        }else if(dp[len] == 0){
            dfs(cost,dp,len-1);
            dfs(cost,dp,len-2);
            dp[len] = Math.min(dp[len-1],dp[len-2]) + cost[len];
        }
    }
}

解决方案三:(空间复杂度为O(n)的迭代):

解决方案:

​ 自下而上地解决这个过程,也就是从子问题入手,根据两个子问题f(i-1)和f(i-2)的解求出f(i)的结果。

源代码:
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int len = cost.length;
        int[] dp = new int[len];
        
        dp[0] = cost[0];
        dp[1] = cost[1];

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

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

解决方案四:(空间复杂度为O(1)的迭代):

解决方案:

​ 前面用一个长度为n的数组将所有f(i)的结果都保存下来。求解f(i)时只需要f(i-1)和f(i-2)的结果,从f(0)到f(i-3)的结果其实对求解f(i)并没有任何作用。也就是说,在求每个f(i)的时候,需要保存之前的f(i-1)和f(i-2)的结果,因此只要一个长度为2的数组即可。

源代码:
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] dp = new int[]{cost[0],cost[1]};
        
        for(int i = 2;i < cost.length;i++){
            dp[i % 2] = Math.min(dp[0],dp[1]) + cost[i];
        }

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

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-07 18:16:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-07 18:16:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-07 18:16:02       87 阅读
  4. Python语言-面向对象

    2024-04-07 18:16:02       96 阅读

热门阅读

  1. 客户主数据冻结

    2024-04-07 18:16:02       45 阅读
  2. MySQL中日期有关函数

    2024-04-07 18:16:02       48 阅读
  3. 54.螺旋矩阵

    2024-04-07 18:16:02       43 阅读
  4. C++ P1152 欢乐的跳

    2024-04-07 18:16:02       32 阅读
  5. LeetCode-热题100:45. 跳跃游戏 II

    2024-04-07 18:16:02       41 阅读
  6. 前端八股文--js系列

    2024-04-07 18:16:02       36 阅读
  7. Go如何并发访问内存

    2024-04-07 18:16:02       90 阅读
  8. 蓝桥杯每日一题(快速幂、组合计数)

    2024-04-07 18:16:02       34 阅读
  9. Anaconda 安装pytorch 问题

    2024-04-07 18:16:02       41 阅读
  10. 使用深度学习识别英文字母和数字

    2024-04-07 18:16:02       143 阅读