Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeetCode 518. Coin Change 2 #24

Open
Woodyiiiiiii opened this issue Apr 23, 2020 · 0 comments
Open

LeetCode 518. Coin Change 2 #24

Woodyiiiiiii opened this issue Apr 23, 2020 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Apr 23, 2020

You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.

Example 1:

Input: amount = 5, coins = [1, 2, 5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

Example 2:

Input: amount = 3, coins = [2]
Output: 0
Explanation: the amount of 3 cannot be made up just with coins of 2.

Example 3:

Input: amount = 10, coins = [10] 
Output: 1

*Note:
You can assume that

  • 0 <= amount <= 5000
  • 1 <= coin <= 5000
  • the number of coins is less than 500
  • the answer is guaranteed to fit into signed 32-bit integer

首先,我一开始想到的是根据Coin change 1的思路,dp[j] += dp[j - coins[i - 1]],然而会出现重复的情况 ,比如coins=[1, 2, 5],当amount == 3时,会出现3 = 1 + 2, 3 = 2 + 1的情况。如何排除多余的情况呢,一开始我想利用最后结果/=2来排除,但会超出整数范围。
既然这样,我们细分dp的状态,将一维数组扩展成二维数组,dp[i][j]表示在j钱下使用了只使用coins[0] ~ coins[i - 1]钱币的组合方法数。为了不让上述重复情况和遗漏情况的发生,我们只算当前coins[i - 1]的方法数,一个一个硬币相加,而不去考虑i - 1之前的硬币使用。比如coins = [1, 2],amount = 3时,当i = 1,我们只算硬币2的增加,所以只会出现[1, 2],不会出现[2, 1]。

class Solution {
    public int change(int amount, int[] coins) {
        int n = coins.length;
        if (n == 0) {
            return amount == 0 ? 1 : 0;
        }
        int[][] dp = new int[n + 1][amount + 1];
        for (int i = 1; i <= n; ++i) {
            dp[i][0] = 1;
            for (int j = 1; j <= amount; ++j) {
                dp[i][j] = dp[i - 1][j] + 
                    (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0);
            }
        }
        
        return dp[n][amount];
    }
}

当然也可以优化成一维数组:

class Solution {
    public int change(int amount, int[] coins) {
        int n = coins.length;
        if (n == 0) {
            return amount == 0 ? 1 : 0;
        }
        int[] dp = new int[amount + 1];
        for (int i = 1; i <= n; ++i) {
            dp[0] = 1;
            for (int j = 1; j <= amount; ++j) {
                dp[j] += (j >= coins[i - 1] ? dp[j - coins[i - 1]] : 0);
            }
        }
        
        return dp[amount];
    }
}

参考资料2有三种递归解法,可以去看一下。


参考资料:

  1. LeetCode
  2. [LeetCode] 518. Coin Change 2 grandyang/leetcode#518
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant