Leetcode 题解 - 动态规划-0-1 背包(5):硬币找零

[LeetCode] Coin Change 硬币找零

dp[i]表示钱数为i时的最小硬币数的找零 这里第一层for  i是1到amount 这个与之前的不同 由于硬币是会出现重复的

所以我们钱数作为dp  每次的钱去硬币数组里面找  代表的事钱 j代表的事硬币index 动态规划还是要得到每一步的结果

min的话初始值都要赋值一个比较大的数字

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

Example 2:
coins = [2], amount = 3
return -1.

Note:
You may assume that you have an infinite number of each kind of coin.

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.

如果大家刷题有一阵子了的,那么应该会知道,对于求极值问题,我们还是主要考虑动态规划Dynamic Programming来做,好处是保留了一些中间状态的计算值,这样可以避免大量的重复计算。我们维护一个一维动态数组dp,其中dp[i]表示钱数为i时的最小硬币数的找零,注意由于数组是从0开始的,所以我们要多申请一位,数组大小为amount+1,这样最终结果就可以保存在dp[amount]中了。初始化dp[0] = 0,因为目标值若为0时,就不需要硬币了。其他值可以初始化是amount+1,为啥呢,因为最小的硬币是1,所以amount最多需要amount个硬币,amount+1也就相当于当前的最大值了,注意这里不能用整型最大值来初始化,因为在后面的状态转移方程有加1的操作,有可能会溢出,除非你先减个1,这样还不如直接用amount+1舒服呢。好,接下来就是要找状态转移方程了,没思路?不要紧!回归例子1,假设我取了一个值为5的硬币,那么由于目标值是11,所以是不是假如我们知道dp[6],那么就知道了组成11的dp值了?所以我们更新dp[i]的方法就是遍历每个硬币,如果遍历到的硬币值小于i值(比如我们不能用值为5的硬币去更新dp[3])时,我们用 dp[i - coins[j]] + 1 来更新dp[i],所以状态转移方程为:

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

dp[i] = min(dp[i], dp[i - coins[j]] + 1);

其中coins[j]为第j个硬币,而i - coins[j]为钱数i减去其中一个硬币的值,剩余的钱数在dp数组中找到值,然后加1和当前dp数组中的值做比较,取较小的那个更新dp数组。先来看迭代的写法如下所示:

因为int数组初始化都为0 所以比较大小你得给它一个不影响的值 这里给的是大于amount的值 方便后面判断

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount + 1];
        int n = coins.length - 1;
        Arrays.fill(dp, amount + 1);
        dp[0] = 0;
        for(int i = 1; i <= amount; i++){
            for(int j = 0; j <= n; j++){
                if(coins[j] <= i)
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
            }
        }
        return (dp[amount] > amount) ? -1 : dp[amount];
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值