这题与动态规划01背包中的目标和问题很相似。
思路分析:
- 创建一个动态规划数组
dp
,其中dp[i]
表示组成金额i
的方式数目。 - 初始化
dp[0]
为 1,表示组成金额 0 的方式只有一种,即不选择任何硬币。 - 遍历硬币数组,对于每个硬币面值,从该面值开始更新
dp
数组。 - 更新
dp[j]
,表示组成金额j
的方式数目为原先的方式数目加上使用当前硬币的方式数目。 - 最终返回
dp[amount]
,即组成目标金额的方式数目。
class Solution {
public:
int change(int amount, vector<int>& coins) {
// 创建一个动态规划数组 dp,其中 dp[i] 表示组成金额 i 的方式数目
vector<int> dp(amount + 1, 0);
// 初始化 dp[0] 为 1,表示组成金额 0 的方式只有一种,即不选择任何硬币
dp[0] = 1;
// 遍历硬币数组,这种先遍历物品在遍历背包的方法算出的是组合数;还有种先遍历背包,后遍历物品的方法算出的是排列数。
for (int i = 0; i < coins.size(); i++) {
// 从当前硬币面值开始更新 dp 数组
for (int j = coins[i]; j <= amount; j++) {
// 更新 dp[j],表示组成金额 j 的方式数目为原先的方式数目加上使用当前硬币 coins[i] 的方式数目
dp[j] += dp[j - coins[i]];
}
}
// 返回组成金额 amount 的方式数目
return dp[amount];
}
};