动态规划相关
动态规划相关
力扣509 斐波那契数列 完全递归解法 / 设置备忘录减少递归次数解法 都是 自顶向下
public int fib(int n) {
/*
* if(n<2){
* return n;
* }
* else{
* return fib(n-1) + fib(n-2);
* }
*/
int[] memo = new int[n + 1];
// 0-n 有效 存储计算出出来的 fib(n)
return dp(memo, n);
}
public int dp(int[] memo, int n) {
if (n == 1 || n == 0) {
return n;
} else {
if (memo[n] != 0) {
// 已经计算过的直接return
return memo[n];
} else {
memo[n] = dp(memo, n - 1) + dp(memo, n - 2);
return memo[n];
}
}
}
力扣 509 斐波那契数列 动态规划 自底向上
public int fib(int n) {
if(n==0 || n==1){
return n;
}
int temp1 = 0;
int temp2 = 1;
int tempR = 0;
for(int i=2;i<=n;i++){
tempR = temp1+temp2;
temp1 = temp2;
temp2 = tempR;
}
return tempR;
}
力扣322 零钱兑换 递归 !!!!!
int[] memo;
public int coinChange(int[] coins, int amount) {
memo = new int[amount + 1];
Arrays.fill(memo, -666);
return dp(coins, amount);
}
// 定义:要凑出金额 n,至少要 dp(coins, n) 个硬币
int dp(int[] coins, int n) {
// 做选择,选择需要硬币最少的那个结果
if (n == 0)
return 0;
if (n < 0)
return -1;
if (memo[n] != -666) {
// 该子问题已经计算过了 直接返回结果
return memo[n];
} else {
int min = Integer.MAX_VALUE;
for (int coin : coins) {
int subProblem = 0;
subProblem = dp(coins, n - coin);
// 若 n-coin>=0 则在dp 函数中的return之前已经完成对memo的更新
if (subProblem == -1) {
// 子问题无解 则跳过
continue;
} else {
// 更新min 子问题的解+1
min = Math.min(subProblem + 1, min);
}
}
memo[n] = Integer.MAX_VALUE > min ? min : -1;
return memo[n];
}
}
力扣322 零钱兑换 动态规划!!!!!
int[] dp;
public int coinChange(int[] coins, int amount) {
dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
// dp数组值 应该为 -1 - amount
// 无解-1
// 有解则最少0个硬币 最多amount个硬币
dp[0] = 0;
for (int i = 1; i < amount + 1; i++) {
for (int coin : coins) {
if (i - coin < 0) {
continue;
} else {
// 已经算到 i 了 则 i-coin 已经算完了
int sub = dp[i - coin] + 1;
// 如果其实 dp[i-coin] 没有被更新计算过 则 dp[i] 依然保持amount+1
// 相当于dp[i] 也没有被计算更新
dp[i] = dp[i] > sub ? sub : dp[i];
// 保证为dp[i]更新最小的
}
}
}
return dp[amount] < amount+1 ? dp[amount] : -1;
// 如果 dp[amount]<amount+1 则说明取到了最少的 硬币数目
// 否则 说明 没有找到解返回-1
}