494. Target Sum
You are given an integer array nums and an integer target.
You want to build an expression out of nums by adding one of the symbols ‘+’ and ‘-’ before each integer in nums and then concatenate all the integers.
- For example, if nums = [2, 1], you can add a ‘+’ before 2 and a ‘-’ before 1 and concatenate them to build the expression “+2-1”.
Return the number of different expressions that you can build, which evaluates to target
Example 1:
Input: nums = [1,1,1,1,1], target = 3
Output: 5
Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
Example 2:
Input: nums = [1], target = 1
Output: 1
Constraints:
- 1 <= nums.length <= 20
- 0 <= nums[i] <= 1000
- 0 <= sum(nums[i]) <= 1000
- -1000 <= target <= 1000
From: LeetCode
Link: 494. Target Sum
Solution:
Ideas:
1. Subset Sum Transformation:
- We convert the problem to a subset sum problem using the formula:
s u b s e t S u m = s u m ( n u m s ) + t a r g e t 2 subsetSum=\frac{sum(nums)+target}{2} subsetSum=2sum(nums)+target - This transformation works because the numbers can either contribute positively or negatively.
2. Dynamic Programming:
- dp[j] represents the number of ways to make a sum j using the elements processed so far.
- We initialize dp[0] = 1 since there’s one way to make sum 0 (using no elements).
3. Iterative Update:
- For each number in nums, we iterate backward from subsetSum to nums[i] to avoid overwriting results in the same iteration.
- Update dp[j] by adding dp[j - nums[i]], representing including nums[i] in the subset.
4. Constraints Handling:
- If the absolute value of target is greater than sum(nums), or if (sum(nums) + target) is odd, return 0 since it’s impossible to split the numbers as required.
5. Space Optimization:
- We use a 1D array (dp) instead of 2D, as only the current state and previous state are needed.
Code:
int findTargetSumWays(int* nums, int numsSize, int target) {
int sum = 0;
for (int i = 0; i < numsSize; i++) {
sum += nums[i];
}
// If the target is outside the range of possible sums or sum + target is odd
if (abs(target) > sum || (sum + target) % 2 != 0) {
return 0;
}
int subsetSum = (sum + target) / 2;
// Dynamic Programming Array to store ways to form subset sums
int* dp = (int*)calloc(subsetSum + 1, sizeof(int));
dp[0] = 1; // Base case: One way to make sum 0 (empty subset)
for (int i = 0; i < numsSize; i++) {
for (int j = subsetSum; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
int result = dp[subsetSum];
free(dp);
return result;
}