题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目描述

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3 
解释: 11 = 5 + 5 + 1
示例 2:

输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。

思路

因为数选择最少的硬币数量,所以需要尽可能多的使用面额较大的硬币。由于输入的面额无序性(这一点是提交代码之后才发现的,踩坑呀。。。)。所以我们首先将面额进行排序(本文采取的由小到大排序,下标从后往前遍历)。

  1. 结束条件

    1. amount%coins[inedx] == 0:此时找到了累加等于amount的面额
    2. index < 0:没有满足情况时,index会一直移动到数组前端
    3. count + amount / coins[index] >= res:硬币数量大于之前的结果res,res为目前的最优值
  2. 递归:amount包含ncoins[index],从n0`开始遍历

代码

  int res = Integer.MAX_VALUE;
  public int coinChange(int[] coins, int amount) {
    if (amount == 0) {
      return 0;
    }
    Arrays.sort(coins);
    coinChange(coins, amount, coins.length - 1, 0);
    return res == Integer.MAX_VALUE ? -1 : res;
  }

    /**
     * 
     * @param coins 面额数组
     * @param amount 金额
     * @param index 当前遍历到的面额数组的下标
     * @param count 使用的硬币数量
     */
  private void coinChange(int[] coins, int amount, int index, int count) {
    if (index < 0 || count + amount / coins[index] >= res) {return;}
    if (amount % coins[index] == 0) {
         res = Math.min(res, count + amount / coins[index]);
      return;
    }

    for (int i = amount / coins[index]; i >= 0; i--) {
      coinChange(coins, amount - i * coins[index], index - 1, count + i);
    }
}
如有疑问,欢迎留言。
微信搜索"程序猿GG的日常"

一枚小白
244 声望3 粉丝

一枚小白