题目要求

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:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

Example 2:
coins = [2], amount = 3
return -1.

Note:
You may assume that you have an infinite number of each kind of coin.

这里模拟实现了一个换钱算法。传入的参数为手上有的纸币的面额以及希望兑换的面额。这里假设纸币的数量是无穷的。

这题本质上考察的是动态规划思想。这里有两种动态规划的方法,分别从递归和非递归的角度解决这个问题。具体的情况还是要看数据的分布情况来确定选择哪种方法。

非递归

这里我们新建一个临时数组result,下标i上的值来存储用当前手上的纸币兑换面额i时所需要的最少的纸币数量。这样,假设有一个纸币数组[coin[0], coint[1], ..., coin[k]],我们需要计算兑换面额i所需要的最小数量的纸币,那么只需要比较[result[i-coin[0]], result[i-coin[1]], result[i-coin[2]] ... , result[i-coint[k]]]即可。这里需要考虑一些越界情况比如手上纸币面额比需兑换面额大。还有可能result[i-coin[t]]是无法兑换的。

    public int coinChange(int[] coins, int amount) {
        if(amount==0) return 0;
        Arrays.sort(coins);
        if(coins==null || coins.length==0 || amount < coins[0]) return -1;
        int[] result = new int[amount+1];
        for(int i = coins[0] ; i<=amount; i++){
            int tmp = Integer.MAX_VALUE;
            for(int j = 0 ; j<coins.length ; j++){
                int remain = i-coins[j];
                if(remain < 0) continue;
                else if(remain==0 || result[remain]!=0){
                    tmp = Math.min(tmp, result[remain]+1);
                }
            }
            result[i] = tmp==Integer.MAX_VALUE ? 0 : tmp;
        }
        return result[amount] == 0 ? -1 : result[amount];
    }

递归

这里需要注意的是,用int数组作为一个缓存来减少重复计算的损耗。其实这里的代码还是可以继续优化的。

    private int[] cache;
    public int coinChange2(int[] coins, int amount){
        cache = new int[amount];
        return coinChangeRecursive(coins, amount);
    }
    
    public int coinChangeRecursive(int[] coins, int amount){
        if(amount<0) return -1;
        if(amount==0) return 0;
        if(cache[amount-1] != 0) return cache[amount-1];
        int min = Integer.MAX_VALUE;
        for(int coin : coins){
            int res = coinChangeRecursive(coins, amount-coin);
            if(res>=0 && res<min){
                min = res+1;
            }
        }
        cache[amount-1] = min==Integer.MAX_VALUE ? -1 : min;
        return cache[amount-1];
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行