【动态规划】322. 零钱兑换

322. 零钱兑换

动态规划-自顶向下

  • 定义 要凑出金额n 至少要dp(coins,n)个硬币
  • 确定base case 目标金额为0 返回0
  • 确定 状态 也就是原问题和子问题中的变量,你每次抽取一个硬币,都会导致目标金额减少,所以状态就是目标金额
  • 确定选择,也就是导致状态产生变化的行为,每次选一个硬币都会导致目标金额的减少
  • 明确dp数组的定义,状态数组的每一个值都是代表目标金额

class Solution {
    int[] memo;
    public int coinChange(int[] coins, int amount) {
        // 创建子问题状态数组
        memo = new int[amount + 1];

        Arrays.fill(memo,-666);// 初始化一个特殊值 表示还没有计算

        // 题目要求的最终结果就是dp
        return dp(coins,amount);
    }

    // 定义 要凑出金额n 至少要dp(coins,n)个硬币
    // dp状态是  变化的 也就是原问题和子问题的变量  由于硬币数量无限,仔细想一下  你每次抽取一个硬币 变化的是什么 目标总金额  抽取硬币的次数就是状态数组的长度  每次抽取 状态变量都会变化
    int dp(int[] coins,int amount){
        // base case
        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 sub  = dp(coins,amount - coin);

            // 子问题无解 就跳过
            if(sub == -1){
                continue;
            }

            // 更新解  因为需要最少拿走硬币的次数
            res = Math.min(res,sub + 1);
        }


        // 将计算结果存入 子问题数组
        memo[amount] = (res == Integer.MAX_VALUE) ? -1:res;
        return res == Integer.MAX_VALUE ? -1:res;
    }
}

动态规划-自底向上

  • 状态数组的每一个状态都是代表目标金额
  • 外层for循环遍历所有状态的所有取值
  • 内层for循环遍历所有状态的所有取值
class Solution {
    public int coinChange(int[] coins, int amount) {
        // int[] dp = new int[amount + 1];

        // 数组大小是  amount + 1
        int[] dp = new int[amount + 1];
        Arrays.fill(dp,amount + 1);

        // base case
        dp[0] = 0;

        // 外层for循环在遍历所有状态的所有取值  每一个状态都是目标金额
        for(int i = 0; i < dp.length; i++){
            // 内层for循环遍历所有状态的所忧取值
            for(int coin:coins){
                // 子问题误解 直接跳过
                if(i - coin < 0){
                    continue;
                }

                dp[i] = Math.min(dp[i], dp[i - coin] + 1);
            }
        }

        return (dp[amount] == amount + 1) ? -1 : dp[amount];
    }
}

你可能感兴趣的:(#,Leetcode,动态规划,算法)