Open In App

Target Sum

Last Updated : 13 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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

Target Sum using Recursion:

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++




// C++ program to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
#include <iostream>
#include <vector>
using namespace std;
 
// Function to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
int findTotalWays(vector<int> arr, int i, int s, int target)
{
 
    // If target is reached, return 1
    if (s == target && i == arr.size())
        return 1;
 
    // If all elements are processed and
    // target is not reached, return 0
    if (i >= arr.size())
        return 0;
 
    // Return total count of two cases
    // 1. Consider current element and add it to current sum
    // target
    // 2. Consider current element and subtract it from
    // current sum.
    return findTotalWays(arr, i + 1, s + arr[i], target)
           + findTotalWays(arr, i + 1, s - arr[i], target);
}
 
// Driver Program
int main()
{
    vector<int> arr = { 1, 1, 1, 1, 1 };
 
    // target number
    int target = 3;
 
    cout << findTotalWays(arr, 0, 0, target) << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
 
public class Main {
    // Function to find the number of ways to calculate
    // a target number using only array elements and
    // addition or subtraction operator.
    static int findTotalWays(List<Integer> arr, int i, int s, int target) {
        // If target is reached, return 1
        if (s == target && i == arr.size()) {
            return 1;
        }
 
        // If all elements are processed and
        // target is not reached, return 0
        if (i >= arr.size()) {
            return 0;
        }
 
        // Return total count of two cases:
        // 1. Consider the current element and add it to the current sum target
        // 2. Consider the current element and subtract it from the current sum.
        return findTotalWays(arr, i + 1, s + arr.get(i), target)
             + findTotalWays(arr, i + 1, s - arr.get(i), target);
    }
 
    // Driver Program
    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);
 
        // target number
        int target = 3;
 
        System.out.println(findTotalWays(arr, 0, 0, target));
    }
}


Python3




# Function to find the number of ways to calculate
# a target number using only array elements and
# addition or subtraction operator.
def findTotalWays(arr, i, s, target):
    # If target is reached, return 1
    if s == target and i == len(arr):
        return 1
 
    # If all elements are processed and
    # target is not reached, return 0
    if i >= len(arr):
        return 0
 
    # Return total count of two cases:
    # 1. Consider the current element and add it to the current sum target
    # 2. Consider the current element and subtract it from the current sum.
    return findTotalWays(arr, i + 1, s + arr[i], target) + findTotalWays(arr, i + 1, s - arr[i], target)
 
# Driver Program
if __name__ == "__main__":
    arr = [1, 1, 1, 1, 1]
 
    # target number
    target = 3
 
    print(findTotalWays(arr, 0, 0, target))


C#




using System;
using System.Collections.Generic;
 
class MainClass
{
    // Function to find the number of ways to calculate
    // a target number using only array elements and
    // addition or subtraction operator.
    static int FindTotalWays(List<int> arr, int i, int s, int target)
    {
        // If target is reached, return 1
        if (s == target && i == arr.Count)
            return 1;
 
        // If all elements are processed and
        // target is not reached, return 0
        if (i >= arr.Count)
            return 0;
 
        // Return the total count of two cases:
        // 1. Consider the current element and add it to the current sum target
        // 2. Consider the current element and subtract it from the current sum.
        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 };
 
        // target number
        int target = 3;
 
        Console.WriteLine(FindTotalWays(arr, 0, 0, target));
    }
}


Javascript




// Function to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
function findTotalWays(arr, i, s, target) {
    // If target is reached, return 1
    if (s === target && i === arr.length) {
        return 1;
    }
 
    // If all elements are processed and
    // target is not reached, return 0
    if (i >= arr.length) {
        return 0;
    }
 
    // Return total count of two cases:
    // 1. Consider the current element and add it to the current sum target
    // 2. Consider the current element and subtract it from the current sum.
    return findTotalWays(arr, i + 1, s + arr[i], target)
         + findTotalWays(arr, i + 1, s - arr[i], target);
}
 
// Driver Program
const arr = [1, 1, 1, 1, 1];
 
// target number
const target = 3;
 
console.log(findTotalWays(arr, 0, 0, target));


Output

5







Time Complexity: O(2n), where n is size of array.
Auxiliary Space: O(n) 

Target Sum using Dynamic Programming (Memoization):

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++




// C++ program to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
#include <iostream>
#include <vector>
using namespace std;
 
// Function to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
int findTotalWays(vector<int>& arr,
                  vector<vector<int> >& dp, int i, int s,
                  int target, int total_sum)
{
 
    // If target is reached, return 1
    if (s == target && i == arr.size())
        return 1;
 
    // If all elements are processed and
    // target is not reached, return 0
    if (i >= arr.size())
        return 0;
 
    // If the result for the current state (i, s +
    // total_sum) has already been computed,
    // return it from the DP table to avoid redundant
    // calculations.
    if (dp[i][s + total_sum] != -1)
        return dp[i][s + total_sum];
 
    // Return total count of two cases
    // 1. Consider current element and add it to current sum
    // target
    // 2. Consider current element and subtract it from
    // current 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);
}
 
// Driver Program
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];
    // target number
    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 {
    // Function to find the number of ways to calculate
    // a target number using only array elements and
    // addition or subtraction operator.
    static int findTotalWays(ArrayList<Integer> arr,
                             int[][] dp, int i, int s,
                             int target, int totalSum)
    {
 
        // If target is reached, return 1
        if (s == target && i == arr.size())
            return 1;
 
        // If all elements are processed and
        // target is not reached, return 0
        if (i >= arr.size())
            return 0;
 
        // If the result for the current state (i, s +
        // totalSum) has already been computed,
        // return it from the DP table to avoid redundant
        // calculations.
        if (dp[i][s + totalSum] != -1)
            return dp[i][s + totalSum];
 
        // Return total count of two cases
        // 1. Consider the current element and add it to the
        // current sum
        //    to reach the target.
        // 2. Consider the current element and subtract it
        // from
        //    the current sum.
        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);
    }
 
    // Driver Program
    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);
 
        // Target number
        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




# Function to find the number of ways to calculate
# a target number using only array elements and
# addition or subtraction operator.
def find_total_ways(arr, dp, i, s, target, total_sum):
    # If target is reached, return 1
    if s == target and i == len(arr):
        return 1
 
    # If all elements are processed and
    # target is not reached, return 0
    if i >= len(arr):
        return 0
 
    # If the result for the current state (i, s +
    # total_sum) has already been computed,
    # return it from the DP table to avoid redundant
    # calculations.
    if dp[i][s + total_sum] != -1:
        return dp[i][s + total_sum]
 
    # Return the total count of two cases:
    # 1. Consider the current element and add it to the current sum target.
    # 2. Consider the current element and subtract it from the current 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]
 
# Driver Program
if __name__ == "__main__":
    arr = [1, 1, 1, 1, 1]
    total_sum = sum(arr)
     
    # Target number
    target = 3
     
    # Create a DP table
    dp = [[-1] * (2 * total_sum + 1) for _ in range(len(arr))]
     
    # Calculate and print the result
    print(find_total_ways(arr, dp, 0, 0, target, total_sum))


C#




using System;
using System.Collections.Generic;
 
class Program {
    // Function to find the number of ways to calculate
    // a target number using only array elements and
    // addition or subtraction operator.
    static int FindTotalWays(List<int> arr, int[, ] dp,
                             int i, int s, int target,
                             int totalSum)
    {
        // If target is reached, return 1
        if (s == target && i == arr.Count)
            return 1;
 
        // If all elements are processed and target is not
        // reached, return 0
        if (i >= arr.Count)
            return 0;
 
        // If the result for the current state (i, s +
        // totalSum) has already been computed, return it
        // from the DP table to avoid redundant
        // calculations.
        if (dp[i, s + totalSum] != -1)
            return dp[i, s + totalSum];
 
        // Return the total count of two cases:
        // 1. Consider the current element and add it to the
        // current sum to reach the target.
        // 2. Consider the current element and subtract it
        // from the current sum.
        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);
    }
 
    // Driver Program
    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];
 
        // Target number
        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 to find the number of ways to calculate
// a target number using only array elements and
// addition or subtraction operator.
function findTotalWays(arr, dp, i, s, target, totalSum) {
    // If the target is reached, return 1
    if (s === target && i === arr.length)
        return 1;
 
    // If all elements are processed and the target is not reached, return 0
    if (i >= arr.length)
        return 0;
 
    // If the result for the current state (i, s + totalSum) has already been computed,
    // return it from the DP table to avoid redundant calculations.
    if (dp[i][s + totalSum] !== -1)
        return dp[i][s + totalSum];
 
    // Return the total count of two cases:
    // 1. Consider the current element and add it to the current sum to reach the target.
    // 2. Consider the current element and subtract it from the current sum to reach the target.
    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];
}
 
// Driver Program
function main() {
    const arr = [1, 1, 1, 1, 1];
    let totalSum = 0;
    for (let i = 0; i < arr.length; i++)
        totalSum += arr[i];
 
    // Target number
    const target = 3;
 
    // Create a 2D DP table
    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();


Output

5







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
Previous
Next
Share your thoughts in the comments

Similar Reads