这道题主要涉及动态规划,利用这个,就能很好解决这个问题。
<!-- more -->java
给定不一样面额的硬币 coins 和一个总金额 amount。编写一个函数来计算能够凑成总金额所需的最少的硬币个数。若是没有任何一种硬币组合能组成总金额,返回 -1。git
示例 1:github
输入: coins = [1, 2, 5], amount = 11 输出: 3 解释: 11 = 5 + 5 + 1
示例 2:segmentfault
输入: coins = [2], amount = 3 输出: -1
说明:函数
你能够认为每种硬币的数量是无限的。学习
原题url:https://leetcode-cn.com/probl...优化
咱们能够从小到大,求出由当前硬币,组成全部金额的最小数,这样最终就是最大金额所能组成的最小硬币数量。url
这种方法核心思想就是记录全部中间状态的结果,若是在实际使用中,你的传入参数amount
是不断变化的,那么用这种方法会比较方法,由于以前的结果能够被重复利用,这样也是一种优点。spa
如今咱们来看看代码:code
class Solution { public int coinChange(int[] coins, int amount) { // 排序,升序 Arrays.sort(coins); // 用来记录中间结果,各类金额所须要的硬币数量 int[] result = new int[amount + 1]; result[0] = 0; // 遍历全部可能的金额 for (int currentAmount = 1; currentAmount <= amount; currentAmount++) { int minNum = Integer.MAX_VALUE; // 遍历全部硬币 for (int j = 0; j < coins.length; j++) { // 当前金额已经比硬币的值小 int remainAmount = currentAmount - coins[j]; if (remainAmount < 0) { break; } // remainAmount没法由硬币组成 if (result[remainAmount] == Integer.MAX_VALUE) { continue; } // 取更小的值 minNum = Math.min(minNum, result[remainAmount] + 1); } result[currentAmount] = minNum; } return result[amount] == Integer.MAX_VALUE ? -1 : result[amount]; } }
提交OK,执行用时:12 ms
,内存消耗:36 MB
,只超过了83.24%
的 java 提交,看来还有优化的空间。
倒不是说动态规划就必定比上面的方法更加优秀,只是也是一种思想,能够利用 dfs(深度优先搜索) 或者 bfs(广度优先搜索),我下面这种写法是 dfs,由于是一路进行到底以后,再去考虑其余状况的。(补充一点,若是使用 bfs 的话,能够借助队列来实现非递归的形式。)
所谓的优化,就是从硬币的使用上来讲,从面值大的开始,而且从可使用数量最大的开始。与此同时,咱们也记录了最小使用数量,若是用当前面值最大的硬币而且使用最多时,依旧大于最小值,那么就不用继续查找了。
以上的优化,实际上是和题目相关联,虽然不能用在其余的题目上,但也能够做为一种思想,值得咱们借鉴和学习。
接下来咱们看看代码:
class Solution { private int minCount = Integer.MAX_VALUE; public int coinChange(int[] coins, int amount) { // 排序 Arrays.sort(coins); // 从大往小找 helper(coins, coins.length - 1, 0, amount); return minCount == Integer.MAX_VALUE ? -1 : minCount; } private void helper(int[] coins, int coinIndex, int curCount, int amount) { if (coinIndex < 0) { return; } // 若是能整除,直接取完 if (amount % coins[coinIndex] == 0) { minCount = Math.min(minCount, curCount + amount / coins[coinIndex]); return; } // 数量上也是从大往小找 for (int i = amount / coins[coinIndex]; i >= 0; i--) { // 由于接下来至少还会用1个币 if (curCount + i + 1 >= minCount) { break; } helper(coins, coinIndex - 1, curCount + i, amount - i * coins[coinIndex]); } } }
提交OK,执行用时:2 ms
,内存消耗:34.7 MB
,超过了100.00%
的 java 提交,有种又快又好的感受。
以上就是这道题目个人解答过程了,不知道你们是否理解了。这道题主要利用动态规划就能够解决,优化的时候须要注意边界条件,从大到小取值,在时间复杂度上能更加优化。
有兴趣的话能够访问个人博客或者关注个人公众号、头条号,说不定会有意外的惊喜。
公众号:健程之道