Combination Sum IV
update Aug 15,2017 18:46
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?
Basic Idea:
虽然叫Combination,但由于事实上可以重复的数字以不同顺序出现在答案中,实际上这是道Permutation的问题。由于每个数字都可以使用不止一次,我们不需要使用used数组,只要无脑dfs即可(在每层dfs中我们都可以选择nums中的任意数字)。由于可能出现重复(不同路径,但是剩余sum相同),我们可以使用一个HashMap存放<remainSum,#result>
,进行 Memoized Searching。
Follow Up 的解法: 由于允许有负数出现,答案就有可能是无穷多个(就像有 negative circle 的 graph 中找固定之外距离的node)。所以,这种情况下,题目就需要限制答案的长度,固定答案长度 <= length
。
Python Code:
class Solution(object):
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
def dfs(nums, remainSum):
if remainSum < 0:
return 0
if remainSum == 0:
return 1
if remainSum in dp:
return dp[remainSum]
ret = 0
for n in nums:
ret += dfs(nums, remainSum - n)
dp[remainSum] = ret
return ret
dp = {}
return dfs(nums, target)
update 2018-07-25 22:14:52
Update:DP,bottom-up solution
我们可以用DP的思路来做,首先我们有如下状态转移:
dp[target] = sum{ dp[target - num] } for num in nums;
base case: dp[0] = 1;
于是,我们只要i从 1 开始向右直到 target,每次检查nums中每个数字,如果target-num >= 0
,生成i的组合个数就加上 dp[target - num]
;
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 0; i < dp.length; ++i) {
for (int num : nums) {
if (i - num >= 0) dp[i] += dp[i - num];
}
}
return dp[target];
}
}