思路分析:
- 创建一个动态规划数组
dp
,其中dp[i]
表示组成金额i
的方式数目。 - 初始化
dp[0]
为 1,表示组成金额 0 的方式只有一种,即不选择任何数字。 - 遍历目标金额范围,对于每个目标金额
j
,遍历可选数字数组。 - 如果当前数字
nums[i]
小于等于目标金额j
且更新dp[j]
不会导致整数溢出,则更新dp[j]
。 - 更新
dp[j]
,表示组成金额j
的方式数目为原先的方式数目加上使用当前数字的方式数目。 - 最终返回
dp[target]
,即组成目标金额的方式数目。
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
// 创建一个动态规划数组 dp,其中 dp[i] 表示组成金额 i 的方式数目
vector<int> dp(target + 1, 0);
// 初始化 dp[0] 为 1,表示组成金额 0 的方式只有一种,即不选择任何数字
dp[0] = 1;
// 遍历目标金额范围,这种先遍历背包后遍历物品的方法就是算的是排列数,与零钱兑换Ⅱ那题对应
for (int j = 0; j <= target; j++) {
// 遍历可选数字数组
for (int i = 0; i < nums.size(); i++) {
// 如果当前数字 nums[i] 小于等于目标金额 j
// 且更新 dp[j] 不会导致整数溢出
if (j >= nums[i] && dp[j] < INT_MAX - dp[j - nums[i]]) {
// 更新 dp[j],表示组成金额 j 的方式数目为原先的方式数目加上使用当前数字 nums[i] 的方式数目
dp[j] += dp[j - nums[i]];
}
}
}
// 返回组成目标金额的方式数目
return dp[target];
}
};