动态规划
1.斐波那契数
1.使用数组存储子问题结果
class Solution {
public int fib(int N) {
if (N == 0) return 0;
int[] dp = new int[N + 1];
// base case
dp[0] = 0; dp[1] = 1;
// 状态转移
for (int i = 2; i <= N; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[N];
}
}
2.使用变量(优化)存储子问题结果
class Solution {
public int fib(int n) {
if (n == 0 || n == 1) {
// base case
return n;
}
// 分别代表 dp[i - 1] 和 dp[i - 2]
int dp_i_1 = 1, dp_i_2 = 0;
for (int i = 2; i <= n; i++) {
// dp[i] = dp[i - 1] + dp[i - 2];
int dp_i = dp_i_1 + dp_i_2;
// 滚动更新
dp_i_2 = dp_i_1;
dp_i_1 = dp_i;
}
return dp_i_1;
}
}
2.爬楼梯
class Solution {
// private Map<Integer,Integer> stroMap = new HashMap<>();
int [] memo;
public int climbStairs(int n) {
memo = new int[n + 1];
return dp(n);
}
int dp(int n){
if(n == 1) return 1;
if(n == 2) return 2;
if(memo[n] > 0){
return memo[n];
}
//状态转移方程
//爬到第n级台阶的方法个数等于爬到 n - 1 的方法个数 和 爬到 n - 2 的方法个数之和
memo[n] = dp(n - 1) + dp(n - 2);
return memo[n];
}
}
3.使用最小花费爬楼梯
- 明确dp[]数组的含义,dp[i]表示爬上i层阶梯需要的最小花费
- 正确初始化,初始化dp[0] == dp[1] == 0
- 由于每一步可以登1层或2层阶梯,那么就由[i - 1](登上i-1需要花费的最小值 + 再向上登需要花费cost[i-1]) 与([i - 2] + cost[i -2 ])中的最小值组成dp[i]
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n+1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 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];
}
}