18.组合总数IV
- 题目描述
给你一个由 不同 整数组成的数组 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
- 思路分析
本题是一个完全背包问题,可以用动态规划解决
//1.创建一个二维dp数组:dp[i][j]:表示目标为j时,选取nums[0-i]去组合恰好达到和为j的个数
//2.初始化二维dp数组:当背包容量为0时即dp[i][0],此时设置dp[i][0]=1,即填满be背包0的方法有1种,即什么也不放
//3.递推公式:本题目是一个完全背包问题,每次可以选择放入相同的nums,则有递推公式,因为要求的是一个排列数,即既要存在{1,2},也要存在{2,1}可以这样去计算每次要求背包容量为j时的情况数,那么就放入物品从物品0,物品1到物品i依次放入,这样就会同时满足放入{1,0}与{0,1}
- Java代码实现
public int combinationSum4(int[] nums, int target) {
//1.创建一个二维dp数组:dp[i][j]:表示目标为j时,
//选取nums[0-i]去组合恰好达到和为j的个数
int[][] dp = new int[nums.length][target + 1];
//2.初始化二维dp数组
for (int i = 0; i < nums.length; i++) {
dp[i][0] = 1;
}
//3.递推公式:
for (int i = 0; i < nums.length; i++) {
for (int j = 1; j <= target; j++) {//上面这两层遍历只是单纯遍历二维数组
for (int k = 0; k <= i; k++) {//对于每个dp[i][j],我们从物品0~i依次放入,这样结果就是排列数
if (nums[k] <= j) {
dp[i][j] += dp[i][j - nums[k]];
}
}
}
}
return dp[nums.length - 1][target];
}