零钱兑换(动态规划)

1、题目:

leetcode_322_零钱兑换: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

2、思路:

求最有解,动态规划解决。

3、代码:

解法1:暴力递归,超时,时间复杂度o(n^2)

class Solution {
    public int coinChange(int[] coins, int amount) {
        if(amount==0) return 0;
        int result = coinChange1(coins, amount);
        if(result==Integer.MAX_VALUE){
            return -1;
        }else{
            return result;
        }
    }

    public static int coinChange1(int[] coins, int amount) {
        if (coins == null || amount < 1) {
            return Integer.MAX_VALUE;
        }
        for (int coin : coins) {
            if (coin == amount) {
                return 1;
            }
        }
        int min = Integer.MAX_VALUE;
        for (int coin : coins) {
            min = Math.min(coinChange1(coins, amount - coin), min);
        }
        if (min == Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        } else {
            return min + 1;
        }
    }
}

 

解法2:动态规划

(1)定义状态:假设dp(n)是凑到n分需要的最少硬币个数

(2)求递推式:

如果第 1 次选择了 25 分的硬币,那么 dp(n) = dp(n – 25) + 1

如果第 1 次选择了 20 分的硬币,那么 dp(n) = dp(n – 20) + 1

如果第 1 次选择了 5 分的硬币,那么 dp(n) = dp(n – 5) + 1

如果第 1 次选择了 1 分的硬币,那么 dp(n) = dp(n – 1) + 1

所以 dp(n) = min { dp(n – 25), dp(n – 20), dp(n – 5), dp(n – 1) } + 1

 

初始状态:

dp[0]=0

所有dp[i]都初始化为Integer.MAX_VALUE

 

    public static int coinChange(int[] coins, int amount) {
        if (coins == null || coins.length == 0) {
            return -1;
        }
        int[] dp = new int[amount + 1];
        for (int i = 1; i < amount + 1; i++) {
            int min = Integer.MAX_VALUE;
            for (int j = 0; j < coins.length; j++) {
                if (i < coins[j] || dp[i - coins[j]] == -1) {
                    continue;
                }
                if (i - coins[j] >= 0) {
                    min = Math.min(min, dp[i - coins[j]]);
                }
            }
            if (min == Integer.MAX_VALUE) {
                dp[i] = -1;
            } else {
                dp[i] = min + 1;
            }
        }
        return dp[amount];
    }

..

 

posted @ 2020-06-27 19:34  guoyu1  阅读(446)  评论(0编辑  收藏  举报