322.零钱兑换

这篇博客探讨了如何使用动态规划解决322题——零钱兑换问题。提供了两种方法:记忆化搜索(自上而下)和动态规划(自下而上)。记忆化搜索通过递归和空间优化避免重复计算,动态规划则通过自底向上的填充数组找到最少硬币组合数。代码示例分别展示了这两种方法的实现。
摘要由CSDN通过智能技术生成

322.零钱兑换

方法一:记忆化搜索(自上而下)

class Solution {
    public int coinChange(int[] coins, int amount) {
        // 初始条件检查
        if (amount < 1) {
            return 0;
        }
        // 动态规划入口
        return coinChange(coins, amount, new int[amount]);
    }

    /**
     * 自上而下的动态规划方法
     * coins:硬币面额
     * rem:余额
     * count:存储中间计算结果,空间换时间
     */
    private int coinChange(int[] coins, int rem, int[] count) {
        // 结束条件:此路径不通
        if (rem < 0) {
            return -1;
        }
        // 结束条件:余额为0,成功结束
        if (rem == 0) {
            return 0;
        }
        // 之前已经计算过这种情况,直接返回结果,避免重复计算
        if (count[rem - 1] != 0) {
            return count[rem - 1];
        }
        int min = Integer.MAX_VALUE;
        // 遍历当前递归子树的每一种情况
        for (int coin : coins) {
            // 用一下coin这个面值的硬币会怎样?res是这个方法的最优情况
            int res = coinChange(coins, rem - coin, count);
            // res<0 即为 res=-1,此法失败,res>min不是最优情况,舍去
            if (res >= 0 && res < min) {
                min = 1 + res;
            }
        }
        // count[rem - 1]存储着给定金额amount的解
        // 若为Integer.MAX_VALUE则该情况无解
        count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
        return count[rem - 1];
    }
}

方法二:动态规划(自下而上)

class Solution {
    //coins = [1, 2, 3], amount = 6
    public int coinChange(int[] coins, int amount) {
        int max = amount + 1;
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, max);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i) {
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值