【LeetCode-Java实现】322. Coin Change

题目描述

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:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.
给一个存放硬币面值的数组(数组中面值可重复使用,且任意数字都可以)和一个需要拼凑出的总金额。
求怎样拼凑,才能使所需的硬币数最少,最终返回最少的硬币数即可。

解题思路

这一题不是最基础的动态规划题了,在LeetCode上属于中等题。
没了解过动态规划的人可能会很自然地想到贪心法,但硬币面值可以是任意数字,贪心法并不总是奏效。
例如:coins=[1,2,7,10],amounts=14
贪心法:每次都取面值最大的:10+2+2=3个硬币
但是肉眼看一下就知道,7+7=2个硬币才是最优解
所以还是要用动态规划。

按惯性思维,用硬币面值来进行动态规划,但是似乎没有什么实际意义,找不出递推关系。

于是考虑使用金额数来进行动态规划:
递推出拼凑所有金额的最少硬币数dp[i]
仍然看上面那个例子,金额 i 可由:
dp[i-1]和coins[0],即1 组合,或者
dp[i-2]和coins[1],即2 组合,或者
dp[i-7]和coins[2],即7 组合,或者
dp[i-10]和coins[3],即10 组合。
使用dp[i]=min(dp[i-1],dp[i-2],dp[i-7],dp[i-10])+1

金额至少要比面值大才需要用该面值进行组合

实现代码

根据上述思路可得Java代码:.

public int coinChange(int[] coins, int amount) {
        //dp[i]:金额为i时所需的最少硬币数     i范围:0~amount
        int[] dp=new int[amount+1];   
        dp[0]=0;  //金额0显然需要0个硬币
        //初始化数组,初始认定所有金额都无法拼凑出
        for(int i=1;i<=amount;i++){
            dp[i]=-1;
        }
        //递推---两层循环
        for(int i=1;i<=amount;i++){                            //外循环:所有金额
            for(int j=0;j<coins.length;j++){                   //内循环:所有硬币面值
                //循环条件
                if(i-coins[j]>=0 && dp[i-coins[j]]!=-1){       //金额i比硬币面值大 &&  i比硬币面值多出的部分能被拼凑出
                    if(dp[i]==-1 || dp[i]>dp[i-coins[j]]+1){   //金额i不能被直接拼凑出  || 拼凑i的最少硬币数比dp[i-coin[j]]+1大
                        dp[i]=dp[i-coins[j]]+1;
                    }
                }
            }
        }
        return dp[amount];
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值