Description
Given an array of distinct integers nums
and a target integer target
, return the number of possible combinations that add up to target
.
The test cases are generated so that the answer can fit in a 32-bit integer.
Examples:
Example 1:
Input: nums = [1,2,3], target = 4
Output: 7
Explanation:
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.
Example 2:
Input: nums = [9], target = 3
Output: 0
Solution in Python
To solve this problem, we need to calculate the number of combinations of elements from the list nums
that sum up to a given target
. Since the order of elements matters, different sequences with the same numbers are considered different combinations.
Approach:
This is a Dynamic Programming (DP) problem, where:
- We define
dp[i]
as the number of ways to achieve a sum ofi
using the numbers innums
. - The solution to the problem will be stored in
dp[target]
.
Steps:
- Define Base Case:
dp[0] = 1
: There is one way to make the sum of0
, which is by choosing no numbers.
- Recurrence Relation:
- For each number
i
from1
totarget
, we iterate through each number innums
. Ifnum <= i
, we adddp[i - num]
todp[i]
because if we already know how many ways we can geti - num
, addingnum
to each of those combinations gives us valid combinations to reachi
.
- For each number
- Iterate and Fill the DP Array:
- We start from
i = 1
up totarget
and fill in the values ofdp[i]
based on previously computed values.
- We start from
- Result:
- The result will be stored in
dp[target]
.
- The result will be stored in
This approach ensures that each sub-problem (sum i
) is solved only once, and it efficiently builds up the solution to target
.
Complexity:
- Time Complexity: O(target×len(nums)) because for each sum from
1
totarget
, we iterate over all elements innums
. - Space Complexity: O(target) for the
dp
array.
Python
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
# Initialize a DP array with (target + 1) elements, all set to 0 initially
dp = [0] * (target + 1)
# Base case: There is one way to achieve a sum of 0 (by using no numbers)
dp[0] = 1
# Fill dp array for each sum from 1 to target
for i in range(1, target + 1):
# For each number in nums, check if it can be used to reach the current sum i
for num in nums:
if i >= num:
# Add the number of ways to make up (i - num) to dp[i]
dp[i] += dp[i - num]
# The result is the number of ways to achieve the sum `target`
return dp[target]
Explanation with Example:
For nums = [1, 2, 3]
and target = 4
:
- Initialize
dp = [1, 0, 0, 0, 0]
. - Compute each
dp[i]
:dp[1]
: Only1
can reach1
, sodp[1] = dp[0] = 1
.dp[2]
:1+1
and2
can reach2
, sodp[2] = dp[1] + dp[0] = 1 + 1 = 2
.dp[3]
:1+1+1
,1+2
, and3
can reach3
, sodp[3] = dp[2] + dp[1] + dp[0] = 2 + 1 + 1 = 4
.dp[4]
:1+1+1+1
,1+1+2
,1+3
,2+2
,3+1
can reach4
, sodp[4] = dp[3] + dp[2] + dp[1] = 4 + 2 + 1 = 7
.
So, dp[4] = 7
, which is the answer.
Solution in C++
C++
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
// Step 1: Create a DP array of size `target + 1` to store the number of ways
// to reach each sum from 0 up to `target`. Initialize all elements to 0.
vector<unsigned int> dp(target + 1, 0);
// Step 2: Base case - there is one way to reach the sum of 0, which is by not
// choosing any elements.
dp[0] = 1;
// Step 3: Fill the DP array. For each intermediate sum from 1 to `target`,
// calculate the number of ways it can be formed using the elements in `nums`.
for (int i = 1; i <= target; i++) {
// Step 4: For each number in `nums`, check if it can be used to form the
// current sum `i`. This is possible if `i - num >= 0`.
for (int num : nums) {
if (i - num >= 0) {
// Step 5: Add the number of ways to reach `i - num` to the number of ways to reach `i`.
dp[i] += dp[i - num];
}
}
}
// Step 6: The answer is the number of ways to reach the target sum.
return dp[target];
}
};
Solution in Javascript
JavaScript
var combinationSum4 = function(nums, target) {
// Initialize a dp array where dp[i] represents the number of combinations to reach sum i.
// Set dp[0] = 1 because there is one way to reach sum 0: by choosing no elements.
const dp = new Array(target + 1).fill(0);
dp[0] = 1;
// Loop through all possible sums from 1 to the target.
for (let i = 1; i <= target; i++) {
// For each sum i, iterate over all numbers in nums.
for (let num of nums) {
// Check if the current number can contribute to the sum i.
if (i >= num) {
// Add the number of ways to form (i - num) to dp[i].
dp[i] += dp[i - num];
}
}
}
// dp[target] now contains the number of combinations to form the target sum.
return dp[target];
};
Solution in Java
Java
class Solution {
public int combinationSum4(int[] nums, int target) {
// DP array where dp[i] represents the number of ways to reach sum i
int[] dp = new int[target + 1];
// Base case: there's one way to get to 0 (by choosing no elements)
dp[0] = 1;
// Loop through each sum from 1 up to the target
for (int currentTarget = 1; currentTarget <= target; currentTarget++) {
// Check each number in the nums array to see if it can contribute
for (int num : nums) {
// Only proceed if the current number is not greater than the currentTarget
if (num <= currentTarget) {
// Add the ways to get to the remaining target after using 'num'
dp[currentTarget] += dp[currentTarget - num];
}
}
}
// dp[target] now contains the number of combinations to reach 'target'
return dp[target];
}
}