小念子

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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

你可以认为每种硬币的数量是无限的

 

 

 解答:

方法1、动态规划

count[amount] = min{ count[amount - coins[0]], count[amount - coins[1]], ..., count[amount - coins[n - 1]] } + 1

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

方法2、dfs

    private int res = Integer.MAX_VALUE;
    public int coinChange(int[] coins, int amount) {
        if (amount == 0) {
            return 0;
        }
        Arrays.sort(coins);
        dfs(coins, amount, 0, coins.length - 1);
        return res == Integer.MAX_VALUE ? -1 : res;
    }
    
    private void dfs(int[] coins, int amount, int count, int index) {
        // index小于零,或者,全部选择当前的结果大于等于res,不取
        if (index < 0 || count + amount / coins[index] >= res) { 
            return;
        }
        // 否则,index大于零,并且,全部选择当前的结果小于res,考虑取
        if (amount % coins[index] == 0) { // 整除,直接取(由于已排序,已经最小,可以直接返回)
            res = count + amount / coins[index];
            return;
        }
        // 不整除,数量从[amount / coins[index]~0], 取当前。递归取下一个index-1
        for (int i = amount / coins[index]; i >= 0; --i) {
            dfs(coins, amount - i * coins[index], count + i, index - 1);
        }
    }

 

posted on 2020-12-23 17:44  小念子  阅读(86)  评论(0编辑  收藏  举报