斐波那契
五部曲
确定dp[i]含义: 第i个斐波那契数值为dp[i]
递推公式: dp[i] = dp[i - 1] + dp [i - 2]
dp数组初始化: dp[0] = 0, dp[1] = 1
遍历顺序: 从前向后
打印dp数组: 为了debug
class Solution {
public int fib(int n) {
if(n <= 1) return n;
int[] dp = new int[n + 1];
//初始化
dp[0] = 0;
dp[1] = 1;
//从前向后遍历, 注意是i<=n
for(int i = 2; i <= n; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
由于只需要前面两个数值就行了, 所以通过滚动数组的方法, 来优化
class Solution {
public int fib(int n) {
if (n < 2) return n;
int a = 0, b = 1, sum = 0;
for (int i = 2; i <= n; i++) {
sum = a + b;
a = b;
b = sum;
}
return b;
}
}
爬楼梯:
- dp[i]: 爬到第i层楼梯, 有dp[i]种方法
- 确定递推公式, 每次只能一步或者两部, 所以dp[i] = dp[i - 1] + dp[i - 2]
- dp数组的初始化, 这里n是正整数, 所以没必要搞0, 只要dp[1]=1, dp[2]=2 (然后从i=3开始推)
- 遍历顺序一定从前往后
- 举例推到dp数组
class Solution {
public int climbStairs(int n) {
if(n<=2) 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 - 1] + dp[i - 2];
}
return dp[n];
}
}
优化空间:
class Solution {
public int climbStairs(int n) {
if(n <= 2) return n;
int a = 1, b = 2, sum = 0;
for(int i = 3; i <= n; i++){
sum = a + b; // f(i - 1) + f(i - 2)
a = b; // 记录f(i - 1),即下一轮的f(i - 2)
b = sum; // 记录f(i),即下一轮的f(i - 1)
}
return b;
}
}
使用最小花费爬楼梯:
可以发现, 到下标0或者下标1是不需要花费体力的, 但是之后就要了
- dp[i]: 到达第i台阶所花费的最少体力为dp[i]
- 数组: dp[i - 1]跳到dp[i]需要花费dp[i - 1] + cost[i - 2], 从dp[i - 2]需要dp[i - 2] + cost[i - 2], 所以取最小值min就行了
- 初始化: 这里题意就是0或1不用体力, 所以dp[0] = 0 dp[1] = 1
- 遍历顺序仍然是从前往后
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length + 1];
dp[0] = 0;
dp[1] = 0;
for(int i = 2; i <= cost.length; i++){
//看清楚, 这里是加上cost
dp[i] = Math.min((dp[i - 1] + cost[i - 1]), (dp[i - 2] + cost[i - 2]));
}
return dp[cost.length];
}
}
优化空间:
class Solution {
public int minCostClimbingStairs(int[] cost) {
int dp0 = 0;
int dp1 = 0;
for(int i = 2; i <= cost.length; i++){
//这里想清楚,dp0是在-2的位置
int dpi = Math.min((dp1 + cost[i - 1]), (dp0 + cost[i - 2]));
dp0 = dp1;
dp1 = dpi;
}
return dp1;
}
}