355 字
2 分钟
动态规划解题思路

动态规划解题思路#

斐波那契数列#

暴力递归

// f(n) 计算第 n 个斐波那契数
static int fib(int n) {
if(n <= 1 && n >= 0) {
return n;
}
return fib(n - 1) + fib(n - 2);
}

使用Memo数组存储,避免重复计算

static long fib2(int n) {
long[] memo = new long[n + 1];
Arrays.fill(memo,-1);
return dp(memo,n);
}
static long dp(long[] memo,int n) {
if(n == 0 || n == 1) {
return n;
}
if(memo[n] != -1) {
return memo[n];
}
memo[n] = dp(memo,n - 1) + dp(memo,n - 2);
return memo[n];
}

零钱兑换#

class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp,amount + 1);
dp[0] = 0;
for(int i = 0;i<dp.length;i++) {
for(int coin : coins) {
if(i - coin < 0) {
continue;
}
dp[i] = Math.min(dp[i],1 + dp[i - coin]);
}
}
return (dp[amount] == amount + 1) ? -1 : dp[amount];
}
}
class Solution {
int[] memo;
public int coinChange(int[] coins, int amount) {
memo = new int[amount + 1];
// 备忘录初始化为一个不会被取到的特殊值,代表还未被计算
Arrays.fill(memo, -666);
return dp(coins, amount);
}
int dp(int[] coins, int amount) {
if (amount == 0) return 0;
if (amount < 0) return -1;
// 查备忘录,防止重复计算
if (memo[amount] != -666)
return memo[amount];
int res = Integer.MAX_VALUE;
for (int coin : coins) {
// 计算子问题的结果
int subProblem = dp(coins, amount - coin);
// 子问题无解则跳过
if (subProblem == -1) continue;
// 在子问题中选择最优解,然后加一
res = Math.min(res, subProblem + 1);
}
// 把计算结果存入备忘录
memo[amount] = (res == Integer.MAX_VALUE) ? -1 : res;
return memo[amount];
}
}