「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。
连续做题和更文14天,也算是在年前达成一个小目标。明天年初一,就是新的起点了。祝大家新年快乐,事事顺心。也希望自己能在新的一年能保持立下的flag都不倒,到下一个年初一,又会是另外一层的欢喜。
题目
给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
示例 1:
输入: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)
请注意,顺序不同的序列被视作不同的组合。
示例 2:
输入:nums = [9], target = 3
输出:0
思路
本题其实是完全背包的一个变种,要求装满背包(target),每个物品可以取0件或者n件,求的个符合条件的排列数量。注意,这里虽然题目叫“组合总数”,但是实际上看了实例1,求的是排列总数。
我们定义一个一维数组dp,dp[n]代表从nums中取和为n排列数量,所以我们最后就是要求解dp[target]。
接下来我们看状态转移方程,由于nums中整数是不同的,所以对dp[n+1],我们可以遍历nums,如果当前num < n + 1,那么就可以尝试把num作为排列的开头,这时,符合条件的排列数量是dp[n+1-num],整理一下,得到dp[n]的递归求解公式,就是我们的状态转移方程:
dp[n] = sum(dp[n-item]) item归属于nums
Java版本代码
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 1; i <= target; i++) {
for (int num : nums) {
if (i >= num) {
dp[i] += dp[i-num];
}
}
}
return dp[target];
}
}