动态规划理论基础
如果某一问题有很多重叠子问题,使用动态规划是最有效的
动态规划是由前一个状态推导出来的,而贪心是局部直接选最优
- 动态规划的解题步骤
- 确定dp数组以及下标的含义
- 确定递归公式
- dp数组如何初始化
- 确定遍历顺序
- 距离推导dp数组
509. 斐波那契数
斐波那契数(通常用
F(n)
表示)形成的序列称为 斐波那契数列。该数列由0
和1
开始,后面的每一项数字都是前面两项数字的和。也就是:F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1
输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
思路一:递归
class Solution {
public int fib(int n) {
if(n==0){
return 0;
}else if(n==1){
return 1;
}
return fib(n-1)+fib(n-2);
}
}
思路二:动规
动规五部曲:
1.确定dp数组以及下标含义
dp[i]的定义为:第i个数的斐波那契的数值为dp[i]
2. 确定递归公式
dp[i]=dp[i-2]+dp[i-1]
3. dp数组初始化
dp[0]=0;
dp[1]=1;
4. 确定遍历顺序
dp[i]依赖dp[i-1]和dp[i-2],所以遍历顺序一定是从前到后遍历的
5. 举例推导dp数组
N为10的时候,dp数组应该如下举例
0 1 1 2 3 5 8 13 21 34 55
class Solution {
public int fib(int n) {
if(n<=1){
return n;
}
int[] dp=new int[n+1];
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
dp[i]=dp[i-2]+dp[i-1];
}
return dp[n];
}
}
70. 爬楼梯
假设你正在爬楼梯。需要
n
阶你才能到达楼顶。每次你可以爬
1
或2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
首先可以看出1阶的方式为1,2阶的方式为2,3阶就是爬2阶+1阶,一次往下类似。。。
动规五部曲:
1. 确定dp数组及下标含义
dp[i]为第i个解题所爬楼的所有方式为dp[i]
2. 确定递归公式
dp[i]=dp[i-2]+dp[i-1]
3. dp数组初始化
dp[1]=1;
dp[2]=2;
4. 确定遍历顺序
同样需要依赖前面的值,所以从前向后遍历
5. 举例推导dp数组
当n=4的时候
1 2 3 5(满足条件,n=4的时候[1,1,1,1],[1,1,2],[1,2,1],[2,1,1],[2,2])
class Solution {
public int climbStairs(int n) {
if(n<=1){
return n;
}
int[] dp=new int[n+1];
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-2]+dp[i-1];
}
return dp[n];
}
}
746. 使用最小花费爬楼梯
给你一个整数数组
cost
,其中cost[i]
是从楼梯第i
个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为
0
或下标为1
的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
动规五部曲
1. 确定dp数组及下表意义
dp[i]表示到达第i层所需要的最低花费为dp[i]
2. 确定递归公式
确定dp[i]需要dp[i-1]和dp[i-2]所决定
dp[i-1]跳到dp[i]需要dp[i-1]+cost[i-1]
dp[i-2]跳到dp[i]需要dp[i-2]+cost[i-2]
所以跳到dp[i]的最低花费为min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
3. dp数组初始化
pd[0]=0;
pd[1]=0;
4. 确定遍历顺序
dp[i]需要由dp[i-1]和dp[i-2]所确定,所以从前向后遍历
5. 举例推导dp数组
class Solution {
public int minCostClimbingStairs(int[] cost) {
int len=cost.length;
int[] pd=new int[len+1];
pd[0]=0;
pd[1]=0;
for(int i=2;i<=len;i++){
pd[i]=Math.min(pd[i-2]+cost[i-2],pd[i-1]+cost[i-1]);
}
return pd[len];
}
}