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?
Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
解法1:递归。按照前面I, II的思路用递归来解,会TLE,比如:OJ一个test case为[4,1,2] 32,结果是39882198,用递归需要好几秒时间。
解法2:动态规划DP来解。这道题类似于322. Coin Change ,建一个一维数组dp,dp[i]表示目标数target为i时解的个数,从1遍历到target,对于每一个数i,遍历nums数组,如果i>=x, dp[i] += dp[i - x]。比如[1,2,3] 4,当计算dp[3]时,3可以拆分为1+x,而x即为dp[2],3也可以拆分为2+x,x为dp[1],3同样可以拆为3+x,x为dp[0],把所有情况加起来就是组成3的所有解。
Java: Recursive
public int combinationSum4(int[] nums, int target) { if (target == 0) { return 1; } int res = 0; for (int i = 0; i < nums.length; i++) { if (target >= nums[i]) { res += combinationSum4(nums, target - nums[i]); } } return res; }
Java:
private int[] dp; public int combinationSum4(int[] nums, int target) { dp = new int[target + 1]; Arrays.fill(dp, -1); dp[0] = 1; return helper(nums, target); } private int helper(int[] nums, int target) { if (dp[target] != -1) { return dp[target]; } int res = 0; for (int i = 0; i < nums.length; i++) { if (target >= nums[i]) { res += helper(nums, target - nums[i]); } } dp[target] = res; return res; }
Java:
public int combinationSum4(int[] nums, int target) { int[] comb = new int[target + 1]; comb[0] = 1; for (int i = 1; i < comb.length; i++) { for (int j = 0; j < nums.length; j++) { if (i - nums[j] >= 0) { comb[i] += comb[i - nums[j]]; } } } return comb[target]; }
Java:
class Solution { public int combinationSum4(int[] nums, int target) { if(nums==null || nums.length==0) return 0; int[] dp = new int[target+1]; dp[0]=1; for(int i=0; i<=target; i++){ for(int num: nums){ if(i+num<=target){ dp[i+num]+=dp[i]; } } } return dp[target]; } }
Python:
class Solution(object): def combinationSum4(self, nums, target): """ :type nums: List[int] :type target: int :rtype: int """ dp = [0] * (target+1) dp[0] = 1 nums.sort() for i in xrange(1, target+1): for j in xrange(len(nums)): if nums[j] <= i: dp[i] += dp[i - nums[j]] else: break return dp[target]
Python:
class Solution(object): def combinationSum4(self, nums, target): nums, combs = sorted(nums), [1] + [0] * (target) for i in range(target + 1): for num in nums: if num > i: break if num == i: combs[i] += 1 if num < i: combs[i] += combs[i - num] return combs[target]
C++:
class Solution { public: int combinationSum4(vector<int>& nums, int target) { vector<int> dp(target + 1, 0); dp[0] = 1; sort(nums.begin(), nums.end()); for (int i = 1; i <= target; ++i) { for (int j = 0; j < nums.size() && nums[j] <= i; ++j) { dp[i] += dp[i - nums[j]]; } } return dp[target]; } };
类似题目:
[LeetCode] 322. Coin Change 硬币找零
[LeetCode] 39. Combination Sum 组合之和
[LeetCode] 40. Combination Sum II 组合之和 II
[LeetCode] 216. Combination Sum III 组合之和 III