代码随想录算法训练营day38 || 509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯

视频讲解:

手把手带你入门动态规划 | LeetCode:509.斐波那契数_哔哩哔哩_bilibili

带你学透动态规划-爬楼梯(对应力扣70.爬楼梯)| 动态规划经典入门题目_哔哩哔哩_bilibili

动态规划开更了!| LeetCode:746. 使用最小花费爬楼梯_哔哩哔哩_bilibili

动态规划理论:

对于动态规划问题,我将拆解为如下五步曲!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

另外关于动态规划与贪心的区别,“动态规划中每一个状态一定是由上一个状态推导出来的;贪心没有状态推导,而是从局部直接选最优的” ,可见贪心可以是动态规划,但是动态规划不一定是贪心,暂时的理解,贪心策略的重心在于针对某个维度寻求其最优,从而间接解题;但是动态规划师多个维度同时考虑,通常是两个维度一同考虑,可能可以涉及三个维度,分别用dp数组下标以及数组元素含义来表示二到三个维度。贪心中出现的重叠区间、两个维度的题目,我们都是单独的操作各个维度。

 509. 斐波那契数

思路:学习掌握动态规划五步走战略。

// 时间复杂度O(n)
// 空间复杂度O(n)

class Solution {
    public int fib(int n) {
        /*
        1、确定dp数组(dp table)以及下标的含义
        2、确定递推公式
        3、dp数组如何初始化
        4、确定遍历顺序
        5、举例推导dp数组
        */
        if(n == 0)
            return 0;
        if(n == 1 || n == 2)
            return 1;
        // 我们五步走
        int[] dp = new int[n];      // 确定数组类型为int,数组的下标代表当前是第i各斐波那契数,每个数组的元素表示的是斐波那契数的值
        // dp[i] = dp[i-1]+dp[i-2]  // 确定递推公式
        dp[0] = 1;
        dp[1] = 1;                  // 完成数组初始化
        for(int i=2; i

70. 爬楼梯

思路:采用注释对本题的求解进行了描述

// 时间复杂度O(n)
// 空间复杂度O(n)

class Solution {
    public int climbStairs(int n) {
        /*
            1、确定dp数组(dp table)以及下标的含义
            2、确定递推公式
            3、dp数组如何初始化
            4、确定遍历顺序
            5、举例推导dp数组
        */
        if(n == 1 || n == 2)
            return n;
        
        // 确定dp数组为int类型,与函数返回类型保持一致;每个下标表示当前是第i节楼梯,数组元素表示爬到第i节楼梯有几种方法
        int[] dp = new int[n];
        // 确定递推方程,表示当前第i节楼梯可以由i-1节和i-2节楼梯爬一次上来,因此i节楼梯的方法数有i-1和i-2两个来源,本题所求的是总共的方法,因此两个位置的方法需求求和,但仅仅只需要求和就好,因为i是延续i-1与i-2这两个来源的方法数,如果只能一次爬一节,那么每一节楼梯都是延续上一节的攀爬方法,全局看只有一种方法
        // dp[i] = dp[i-1]+dp[i-2]+1;   
        dp[0] = 1;
        dp[1] = 2;
        for(int i=2; i

746. 使用最小花费爬楼梯

思路:采用注释对本题的求解进行了描述。

// 时间复杂度O(n)
// 空间复杂度O(n+1)

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        if(cost.length == 1)
            return cost[0];
        if(cost.length == 2)
            return Math.min(cost[0], cost[1]);

        /*
            1、确定dp数组(dp table)以及下标的含义
            2、确定递推公式
            3、dp数组如何初始化
            4、确定遍历顺序
            5、举例推导dp数组
        */
        
        // 确定dp数组,数组下标表示当前是第i节楼梯,数组值表示当前爬到此处所消耗的最小的体力
        // 因此dp[i]是不包括cost[i]的,而是在后续i+1位置或者i+2位置考虑最小体力时,需要dp[i]加上cost[i]来表示是从i位置出发往上的
        int n = cost.length;
        // 另外题目中表示cost数组中每个元素表示一节楼梯,必须要超过整个数组,即到达cost.length处才算到达顶楼,所以dp的长度为n+1.返回的值也是dp[n],而不是dp[n-1]
        int[] dp = new int[n+1];
        // 根据题意,可以从1级或2级楼梯直接开始,因此初始化都是0
        dp[0] = dp[1] = 0;
        // 与初始化元素所处在的位置保持一致
        for(int i=2; i<=n; i++){
            dp[i] = Math.min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]); 
        }

        return dp[n];
    }
}

你可能感兴趣的:(算法,leetcode,动态规划)