Target Sum
Last Updated :
13 Nov, 2023
Given an array arr[] of length N and an integer target. You want to build an expression out of arr[] by adding one of the symbols ‘+‘ and ‘–‘ before each integer in arr[] and then concatenate all the integers. Return the number of different expressions that can be built, which evaluates to target.
Example:
Input : N = 5, arr[] = {1, 1, 1, 1, 1}, target = 3
Output: 5
Explanation:
There are 5 ways to assign symbols to
make the sum of array 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 = 3
Input: N = 1, arr[] = {1}, target = 1
Output: 1
The problem can be solved by recursively exploring all possible ways to combine the integers in the array while adding or subtracting them to reach the target sum. At each step, there are two choices: either add the current element to the running total or subtract it.
Let’s findTotalWays(arr, i, s, target) tells us number of ways to reach target, if first i elements have been considered and current sum is s.
Recurrence Relation:
findTotalWays(arr, i, s, target) = findTotalWays(arr, i+1,s +arr[i], target) + findTotalWays(arr, i+1, s-arr[i], target)
For each element, there are 2 options.
- Add the current element: If we add the current element to running total then current sum will become s+arr[i]. Call the findTotalWays() function recursively with the updated current sum and the remaining elements of array i.e., findTotalWays(arr, i+1,s +arr[i], target)
- Subtract the current element: If we subtract the current element from running total then current sum will become s-arr[i]. Call the findTotalWays() function recursively with the updated current sum and the remaining elements of array i.e., findTotalWays(arr, i+1,s -arr[i], target)
Base case:
- If the target sum is reached (i.e., s becomes equal to target sum) and all elements in the array have been processed, return 1. This represents a valid way to form the target sum.
- If all elements in the array have been processed but the target sum has not been reached (i.e., s is not equal to target sum), return 0. This indicates expression does not evaluates to target.
Below is recursive implementation of above idea.
C++
#include <iostream>
#include <vector>
using namespace std;
int findTotalWays(vector< int > arr, int i, int s, int target)
{
if (s == target && i == arr.size())
return 1;
if (i >= arr.size())
return 0;
return findTotalWays(arr, i + 1, s + arr[i], target)
+ findTotalWays(arr, i + 1, s - arr[i], target);
}
int main()
{
vector< int > arr = { 1, 1, 1, 1, 1 };
int target = 3;
cout << findTotalWays(arr, 0, 0, target) << endl;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class Main {
static int findTotalWays(List<Integer> arr, int i, int s, int target) {
if (s == target && i == arr.size()) {
return 1 ;
}
if (i >= arr.size()) {
return 0 ;
}
return findTotalWays(arr, i + 1 , s + arr.get(i), target)
+ findTotalWays(arr, i + 1 , s - arr.get(i), target);
}
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>();
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
int target = 3 ;
System.out.println(findTotalWays(arr, 0 , 0 , target));
}
}
|
Python3
def findTotalWays(arr, i, s, target):
if s = = target and i = = len (arr):
return 1
if i > = len (arr):
return 0
return findTotalWays(arr, i + 1 , s + arr[i], target) + findTotalWays(arr, i + 1 , s - arr[i], target)
if __name__ = = "__main__" :
arr = [ 1 , 1 , 1 , 1 , 1 ]
target = 3
print (findTotalWays(arr, 0 , 0 , target))
|
C#
using System;
using System.Collections.Generic;
class MainClass
{
static int FindTotalWays(List< int > arr, int i, int s, int target)
{
if (s == target && i == arr.Count)
return 1;
if (i >= arr.Count)
return 0;
return FindTotalWays(arr, i + 1, s + arr[i], target)
+ FindTotalWays(arr, i + 1, s - arr[i], target);
}
public static void Main( string [] args)
{
List< int > arr = new List< int > { 1, 1, 1, 1, 1 };
int target = 3;
Console.WriteLine(FindTotalWays(arr, 0, 0, target));
}
}
|
Javascript
function findTotalWays(arr, i, s, target) {
if (s === target && i === arr.length) {
return 1;
}
if (i >= arr.length) {
return 0;
}
return findTotalWays(arr, i + 1, s + arr[i], target)
+ findTotalWays(arr, i + 1, s - arr[i], target);
}
const arr = [1, 1, 1, 1, 1];
const target = 3;
console.log(findTotalWays(arr, 0, 0, target));
|
Time Complexity: O(2n), where n is size of array.
Auxiliary Space: O(n)
The above recursive solution has Optimal Substructure and Overlapping Subproblems so Dynamic programming (Memoization) can be used to solve the problem. So, 2D array can be used to store results of previously calculated subproblems.
Follow the below steps to Implement the idea:
- Create a 2D dp array to store the results of previously solved subproblems.
- dp[i][j] will represent the number of distinct expressions to make the target sum if first i elements have even considered and the current sum is j.
- During the recursion call, if the same state is called more than once, then we can directly return the answer stored in dp for that state instead of calculating again.
- Notice that total_sum is added to current sum in recursive function to ensure that the memoization table can handle both positive and negative sums.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <vector>
using namespace std;
int findTotalWays(vector< int >& arr,
vector<vector< int > >& dp, int i, int s,
int target, int total_sum)
{
if (s == target && i == arr.size())
return 1;
if (i >= arr.size())
return 0;
if (dp[i][s + total_sum] != -1)
return dp[i][s + total_sum];
return dp[i][s + total_sum]
= findTotalWays(arr, dp, i + 1, s + arr[i],
target, total_sum)
+ findTotalWays(arr, dp, i + 1, s - arr[i],
target, total_sum);
}
int main()
{
vector< int > arr = { 1, 1, 1, 1, 1 };
int total_sum = 0;
for ( int i = 0; i < arr.size(); i++)
total_sum += arr[i];
int target = 3;
vector<vector< int > > dp(
arr.size(), vector< int >(2 * total_sum + 1, -1));
cout << findTotalWays(arr, dp, 0, 0, target, total_sum)
<< endl;
return 0;
}
|
Java
import java.util.ArrayList;
public class Main {
static int findTotalWays(ArrayList<Integer> arr,
int [][] dp, int i, int s,
int target, int totalSum)
{
if (s == target && i == arr.size())
return 1 ;
if (i >= arr.size())
return 0 ;
if (dp[i][s + totalSum] != - 1 )
return dp[i][s + totalSum];
return dp[i][s + totalSum]
= findTotalWays(arr, dp, i + 1 , s + arr.get(i),
target, totalSum)
+ findTotalWays(arr, dp, i + 1 ,
s - arr.get(i), target,
totalSum);
}
public static void main(String[] args)
{
ArrayList<Integer> arr = new ArrayList<>();
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
arr.add( 1 );
int totalSum = 0 ;
for ( int i = 0 ; i < arr.size(); i++)
totalSum += arr.get(i);
int target = 3 ;
int [][] dp = new int [arr.size()][ 2 * totalSum + 1 ];
for ( int i = 0 ; i < arr.size(); i++) {
for ( int j = 0 ; j < 2 * totalSum + 1 ; j++) {
dp[i][j] = - 1 ;
}
}
System.out.println(
findTotalWays(arr, dp, 0 , 0 , target, totalSum));
}
}
|
Python
def find_total_ways(arr, dp, i, s, target, total_sum):
if s = = target and i = = len (arr):
return 1
if i > = len (arr):
return 0
if dp[i][s + total_sum] ! = - 1 :
return dp[i][s + total_sum]
dp[i][s + total_sum] = find_total_ways(arr, dp, i + 1 , s + arr[i], target, total_sum) + \
find_total_ways(arr, dp, i + 1 , s - arr[i], target, total_sum)
return dp[i][s + total_sum]
if __name__ = = "__main__" :
arr = [ 1 , 1 , 1 , 1 , 1 ]
total_sum = sum (arr)
target = 3
dp = [[ - 1 ] * ( 2 * total_sum + 1 ) for _ in range ( len (arr))]
print (find_total_ways(arr, dp, 0 , 0 , target, total_sum))
|
C#
using System;
using System.Collections.Generic;
class Program {
static int FindTotalWays(List< int > arr, int [, ] dp,
int i, int s, int target,
int totalSum)
{
if (s == target && i == arr.Count)
return 1;
if (i >= arr.Count)
return 0;
if (dp[i, s + totalSum] != -1)
return dp[i, s + totalSum];
return dp[i, s + totalSum]
= FindTotalWays(arr, dp, i + 1, s + arr[i],
target, totalSum)
+ FindTotalWays(arr, dp, i + 1, s - arr[i],
target, totalSum);
}
static void Main()
{
List< int > arr = new List< int >{ 1, 1, 1, 1, 1 };
int totalSum = 0;
for ( int i = 0; i < arr.Count; i++)
totalSum += arr[i];
int target = 3;
int [, ] dp = new int [arr.Count, 2 * totalSum + 1];
for ( int i = 0; i < arr.Count; i++) {
for ( int j = 0; j < 2 * totalSum + 1; j++) {
dp[i, j] = -1;
}
}
Console.WriteLine(
FindTotalWays(arr, dp, 0, 0, target, totalSum));
}
}
|
Javascript
function findTotalWays(arr, dp, i, s, target, totalSum) {
if (s === target && i === arr.length)
return 1;
if (i >= arr.length)
return 0;
if (dp[i][s + totalSum] !== -1)
return dp[i][s + totalSum];
dp[i][s + totalSum] = findTotalWays(arr, dp, i + 1, s + arr[i], target, totalSum)
+ findTotalWays(arr, dp, i + 1, s - arr[i], target, totalSum);
return dp[i][s + totalSum];
}
function main() {
const arr = [1, 1, 1, 1, 1];
let totalSum = 0;
for (let i = 0; i < arr.length; i++)
totalSum += arr[i];
const target = 3;
const dp = new Array(arr.length);
for (let i = 0; i < arr.length; i++) {
dp[i] = new Array(2 * totalSum + 1).fill(-1);
}
console.log(findTotalWays(arr, dp, 0, 0, target, totalSum));
}
main();
|
Time Complexity: O(N*S), where N is size of array and S is total space.
Auxiliary Space: O(N*S)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...