题目:
难度:中等
动态规划:
dp[i][j] 定义 :可选前 i 种硬币的情况下,组成金额 j 的组合数。
初始状态:
- dp[0][j] = 0, 1 <= j <= amount(不选取任何硬币的情况下,组成正整数金额的组合数为0)
- dp[i][0] = 1, 0 <= i <= n(金额为0的情况下,只有空集的这一种组合才是0)
状态转移方程:
cpp
if(j - coins[i - 1] >= 0) // 容量足够选取该硬币:组合数=选取该硬币和不选该硬币两种状态相加
dp[i][j] = dp[i][j - coins[i - 1]] + dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j]; // 容量不足以选取该硬币:组合数=不选该硬币的组合数
代码:
cpp
class Solution {
public:
int change(int amount, vector<int>& coins) {
int n = coins.size();
vector<vector<int>> dp(n + 1, vector<int>(amount + 1, 0)); // dp[i][j]:i代表使用前i种硬币,j代表金额
for(int i = 0; i <= n; i++) // 初始化,组成金额为0的方案数总是1(不选任何硬币)
dp[i][0] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= amount; j++)
{
if(j - coins[i - 1] >= 0) // 容量足够选取该硬币:组合数=选取该硬币和不选该硬币两种状态相加
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];
}
};
时间复杂度O(N * amount),N是coins数组长度。
空间复杂度O(N * amount)。