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
题意:给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
解法 完全背包
设 dp[i][j]
为用前 i
种货币凑成总金额 j
的硬币组合数,则等于用前 i - 1
种货币凑成总金额 j
的硬币组合数,加上用前 i
种货币凑成总金额 j - coins[i]
的组合数。以例1为示:
i/val 0 1 2 3 4 5
0 1 0 0 0 0 0
1 1 1 1 1 1 1
2 1 1 2 2 3 3
5 1 1 2 2 3 4
class Solution {
public:
int change(int amount, vector<int>& coins) {
int n = coins.size();
vector<vector<int>> dp(n + 1, vector<int>(amount + 1));
for (int i = 0; i <= n; ++i) dp[i][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= amount; ++j) {
if (j >= coins[i - 1]) dp[i][j] = dp[i][j - coins[i - 1]] + dp[i - 1][j];
else dp[i][j] = dp[i - 1][j];
}
}
return dp[n][amount];
}
};
效率如下:
执行用时:48 ms, 在所有 C++ 提交中击败了23.94% 的用户
内存消耗:17.9 MB, 在所有 C++ 提交中击败了15.97% 的用户
空间优化如下:
class Solution {
public:
int change(int amount, vector<int>& coins) {
int n = coins.size();
vector<int> dp(amount + 1);
dp[0] = 1;
for (int i = 1; i <= n; ++i)
for (int j = coins[i - 1]; j <= amount; ++j)
dp[j] += dp[j - coins[i - 1]];
return dp[amount];
}
};
运行效率如下:
执行用时:8 ms, 在所有 C++ 提交中击败了96.17% 的用户
内存消耗:6.9 MB, 在所有 C++ 提交中击败了51.78% 的用户