【LeetCode-Java实现】322. Coin Change

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];
    }

你可能感兴趣的:(LeetCode,动态规划)