视频讲解:
手把手带你入门动态规划 | LeetCode:509.斐波那契数_哔哩哔哩_bilibili
带你学透动态规划-爬楼梯(对应力扣70.爬楼梯)| 动态规划经典入门题目_哔哩哔哩_bilibili
动态规划开更了!| LeetCode:746. 使用最小花费爬楼梯_哔哩哔哩_bilibili
动态规划理论:
对于动态规划问题,我将拆解为如下五步曲!
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导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<n; i++) //遍历顺序与初始化元素所处位置保持一致dp[i] = dp[i-1]+dp[i-2];return dp[n-1];}
}
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<n; i++){dp[i] = dp[i-1]+dp[i-2];}return dp[n-1];}
}
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级楼梯直接开始,因此初始化都是0dp[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];}
}