Leetcode:322-零钱兑换

题目:

给定不同面额的硬币(coins)和一个总金额(amount)。写一个函数来计算可以
凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合方式能组成总金额,返回-1。
示例 1:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

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

注意:你可以认为每种硬币的数量是无限的。

思路:

这个问题个0-1背包问题类似,区别在于每种硬币可以重复使用;做法是从最小的硬币开始,去构成目标解,直到得到的解大于目标解,就使用下一个硬币组合构成。

class Solution {
    private static int maxValue = 100000000;
    public int search(int index, int amount, int[] coins){
        if(index >= coins.length){
            return maxValue;
        }

        if(amount == 0){
            return 0;
        }

        if(amount < 0){
            return maxValue;
        }

        return Math.min(search(index, amount - coins[index], coins) + 1, 
                        search(index + 1, amount, coins));
    }

    public int coinChange(int[] coins, int amount) {
        int val = search(0, amount, coins);
        if(val < maxValue){
            return val;
        }else{
            return -1;
        }
    }
}

动态规划:将计算结果保存在特定结构里,这种结构可能是(一维数组、二维数组、三维数组或者Map),将原始问题分解成子问题,先求子问题,从这些子问题的解得到原始问题的解。

class Solution {
    private static int[][] result;

    private static int maxValue = 100000000;
    public int search(int index, int amount, int[] coins){
        if(index >= coins.length){
            return maxValue;
        }

        if(amount == 0){
            return 0;
        }

        if(amount < 0){
            return maxValue;
        }

        if(result[index][amount] >= 0){
            return result[index][amount];
        }

        result[index][amount] = Math.min(search(index, amount - coins[index], coins) + 1, 
                        search(index + 1, amount, coins));
        return result[index][amount];
    }

    public int coinChange(int[] coins, int amount) {
        result = new int[20][10000];
        for(int i = 0;i < 20; i++){
            for(int j = 0; j < 10000; j++){
                result[i][j] = -1;
            }
        }

        int val = search(0, amount, coins);
        if(val < maxValue){
            return val;
        }else{
            return -1;
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值