题目
给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
示例
输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。
解析
根据示例,虽说写的是求组合,但其实是要求排列,且求的是排列的个数;
如下要点要牢记:
求组合数:外层for循环遍历物品,内层for遍历背包。
求排列数:外层for遍历背包,内层for循环遍历物品。
再来一遍动规五部曲:
1.确定dp数组以及下标的含义
dp[i]: 凑成目标正整数为i的排列个数为dp[i];即i是背包容量,dp[i]是个数
2.确定递推公式
在目标和和 零钱兑换II中也是一样,求装满背包有几种方法,递推公式一般都是:
dp[i] += dp[i - nums[j]]; (背下来)
func combinationSum4(nums []int, target int) int {
// 首先题目写的是组合,但根据示例,其实是排列
// 如果是排列,那么遍历背包的顺序就是先背包,再物品了
dp := make([]int, target+1) // 背包容量为target+1
dp[0] = 1
for i := 0; i <= target; i++ { // i是背包,可以等于
for j := 0; j < len(nums); j++ { // j是物品
if i - nums[j] >= 0 { // 这一行表示此次循环中这个背包还能装下
dp[i] += dp[i-nums[j]] //注意谁是i,谁是j
}
}
}
return dp[target]
}