Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.
Example:
nums = [1, 2, 3] target = 4 The possible combination ways are: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) Note that different sequences are counted as different combinations. Therefore the output is 7.
Follow up:
What if negative numbers are allowed in the given array?
How does it change the problem?
What limitation we need to add to the question to allow negative numbers?
题意:给出一个数组和目标和,求数组中的数组成目标和一共有多少种方式。
思路:利用动态规划的思想,用dp[]数组记录每个数能被组合的总的方法,以给出的例子为例:
- 1的组合总数dp[0]:0 ;
- 1的组合总数dp[1]:1 --(1) ;
- 2的组合总数dp[2]:2 --(1,1)、(2);
- 3的组合总数dp[3]:2 --(1,1,1)、(1,2)、(2,1)、(3);
- 4的组合总数dp[4]:7 --(1, 1, 1, 1) 、(1, 1, 2) 、(1, 2, 1) 、(1, 3) 、(2, 1, 1) 、(2, 2) 、(3, 1)
其实可以得出前4位数的关系:
- 如果nums中包含了target,那么target就能被nums中这一个数组合。
- 如果nums中存在比target小的数num[i],那么target的组合数就能累加上(target-nums[i])的组合数,如当target=3,遍历nums中小于等于target的数num:
- 当num=1,dp[1]=1, dp[target-num]=dp[3-1]=dp[2]=2;
- 当num=2,dp[2]=2,dp[target-num]=dp[3-2]=dp[1]=1;
- 当num=3,dp[3]=1,dp[target-num]=dp[3-3]=dp[0]=0; (dp[3]=1是因为已知一种可直接组合成target=3的方式:当num=3)
可以得出结论:dp[3]=dp[3]+dp[3-1]+dp[3-2]+dp[3-3]=dp[3]+dp[2]+dp[1]+dp[0]=1+2+1=4.
总结成公式:当nums[]中的数num<=target,
dp[target] = dp[target] + dp[target-nums1] + dp[target-nums2] +···+ dp[target-numsN]
(numN<=target);
代码:
class Solution {
public int combinationSum4(int[] nums, int target) {
int length = nums.length;
int[] dp = new int[target+1];
for(int num:nums){
if(num<=target){
dp[num]=1; //自身就能形成一种组合方式
}
}
for(int i=1;i<=target;i++){
for(int num:nums){
if(num<=i){
int subNum = i-num;
dp[i]+=dp[subNum]; //自身的组合总数 = (自身-数组中存在的数)的组合总数
}
}
}
return dp[target];
}
}