Open In App

Count ways to split array into two equal sum subarrays by changing sign of any one array element

Given an array arr[] consisting of N integers, the task is to count ways to split array into two subarrays of equal sum by changing the sign of any one array element.

Examples:



Input: arr[] = {2, 2, -3, 3}
Output: 2
Explanation:
Changing arr[0] = 2 to arr[0] = -2, the array becomes {-2, 2, -3, 3}. Only 1 possible split is {-2, 2} and {-3, 3}.
Changing arr[1] = 2 to arr[1] = -2, the array becomes {2, -2, -3, 3}. Only 1 possible split is {-2, 2} and {-3, 3}.
Changing arr[2] = -3 to arr[2] = 3, the array becomes {2, 2, 3, 3}. No way to split the array.
Changing arr[3] = 3 to arr[2] = -3, the array becomes {2, 2, -3, -3}. No way to split the array.
Therefore, the total number of ways to split = 1 + 1 + 0 + 0 = 2.

Input: arr[] = {2, 2, 1, -3, 3}
Output: 0



Naive Approach: The simplest approach to solve the problem is to traverse the array and change the sign of every array element one by one and count the number of ways to split array into two equal sum subarrays for every alteration. Finally, print the sum of all possible ways. 
Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to store the prefix sum and suffix sum for every array indices to find the sum of the splitter subarrays in O(1) computational complexity. Follow the steps below to solve the problem:

Below is the implementation of the above approach:




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count ways of splitting
// the array in two subarrays of equal
// sum by changing sign of any 1 element
int countSubArraySignChange(int arr[], int N)
{
    // Stores the count of elements
    // in prefix and suffix of array
    unordered_map<int, int> prefixCount;
    unordered_map<int, int> suffixCount;
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--) {
 
        total += arr[i];
 
        // Increase the frequency of
        // current element in suffix
        suffixCount[arr[i]]++;
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++) {
 
        // Modify prefix sum
        prefixSum += arr[i];
 
        // Add arr[i] to prefix Map
        prefixCount[arr[i]]++;
 
        // Calculate suffix sum by
        // subtracting prefix sum
        // from total sum of elements
        suffixSum = total - prefixSum;
 
        // Remove arr[i] from suffix Map
        suffixCount[arr[i]]--;
 
        // Store the difference
        // between the subarrays
        int diff = prefixSum - suffixSum;
 
        // Check if diff is even or not
        if (diff % 2 == 0) {
 
            // Count number of ways to
            // split array at index i such
            // that subarray sums are same
            int x = prefixCount
                    + suffixCount[-diff / 2];
 
            // Update the count
            count = count + x;
        }
    }
 
    // Return the count
    return count;
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 2, -3, 3 };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << countSubArraySignChange(arr, N);
 
    return 0;
}




// Java program for the above approach
import java.util.*;
class GFG{
 
// Function to count ways of splitting
// the array in two subarrays of equal
// sum by changing sign of any 1 element
static int countSubArraySignChange(int arr[], int N)
{
   
    // Stores the count of elements
    // in prefix and suffix of array
    HashMap<Integer,Integer> prefixCount = new HashMap<Integer,Integer>();
    HashMap<Integer,Integer> suffixCount = new HashMap<Integer,Integer>();
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--)
    {
 
        total += arr[i];
 
        // Increase the frequency of
        // current element in suffix
        if(suffixCount.containsKey(arr[i])){
            suffixCount.put(arr[i], suffixCount.get(arr[i]) + 1);
        }
        else{
            suffixCount.put(arr[i], 1);
        }
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++)
    {
 
        // Modify prefix sum
        prefixSum += arr[i];
 
        // Add arr[i] to prefix Map
        if(prefixCount.containsKey(arr[i]))
        {
            prefixCount.put(arr[i], prefixCount.get(arr[i])+1);
        }
        else
        {
            prefixCount.put(arr[i], 1);
        }
 
        // Calculate suffix sum by
        // subtracting prefix sum
        // from total sum of elements
        suffixSum = total - prefixSum;
 
        // Remove arr[i] from suffix Map
        if(suffixCount.containsKey(arr[i]))
        {
            suffixCount.put(arr[i], suffixCount.get(arr[i]) - 1);
        }
 
        // Store the difference
        // between the subarrays
        int diff = prefixSum - suffixSum;
 
        // Check if diff is even or not
        if (diff % 2 == 0)
        {
 
            // Count number of ways to
            // split array at index i such
            // that subarray sums are same
            int x = (prefixCount.containsKey(diff / 2)?prefixCount.get(diff / 2):0)
                    + (suffixCount.containsKey(-diff / 2)?suffixCount.get(-diff / 2):0);
 
            // Update the count
            count = count + x;
        }
    }
 
    // Return the count
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 2, 2, -3, 3 };
    int N = arr.length;
 
    // Function Call
    System.out.print(countSubArraySignChange(arr, N));
}
}
 
// This code is contributed by 29AjayKumar




# Python3 program for the above approach
 
# Function to count ways of splitting
# the array in two subarrays of equal
# sum by changing sign of any 1 element
def countSubArraySignChange(arr, N):
     
    # Stores the count of elements
    # in prefix and suffix of array
    prefixCount = {}
    suffixCount = {}
 
    # Stores the total sum of array
    total = 0
 
    # Traverse the array
    for i in range(N - 1, -1, -1):
 
        total += arr[i]
 
        # Increase the frequency of
        # current element in suffix
        suffixCount[arr[i]] = suffixCount.get(arr[i], 0) + 1
 
    # Stores prefix sum upto
    # an index
    prefixSum = 0
 
    # Stores sum of suffix
    # from an index
    suffixSum = 0
 
    # Stores the count of ways to
    # split the array in 2 subarrays
    # having equal sum
    count = 0
 
    # Traverse the array
    for i in range(N - 1):
 
        # Modify prefix sum
        prefixSum += arr[i]
 
        # Add arr[i] to prefix Map
        prefixCount[arr[i]] = prefixCount.get(arr[i], 0) + 1
 
        # Calculate suffix sum by
        # subtracting prefix sum
        # from total sum of elements
        suffixSum = total - prefixSum
 
        # Remove arr[i] from suffix Map
        suffixCount[arr[i]] -= 1
 
        # Store the difference
        # between the subarrays
        diff = prefixSum - suffixSum
 
        # Check if diff is even or not
        if (diff % 2 == 0):
 
            # Count number of ways to
            # split array at index i such
            # that subarray sums are same
            y, z = 0, 0
            if -diff//2 in suffixCount:
                y = suffixCount[-dff//2]
            if diff//2 in prefixCount:
                z = prefixCount
            x = z+ y
 
            # Update the count
            count = count + x
 
    # Return the count
    return count
 
# Driver Code
if __name__ == '__main__':
    arr=[2, 2, -3, 3]
    N = len(arr)
 
    # Function Call
    print(countSubArraySignChange(arr, N))
 
    # This code is contributed by mohit kumar 29




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
  // Function to count ways of splitting
  // the array in two subarrays of equal
  // sum by changing sign of any 1 element
  static int countSubArraySignChange(int []arr, int N)
  {
 
    // Stores the count of elements
    // in prefix and suffix of array
    Dictionary<int,int> prefixCount = new Dictionary<int,int>();
    Dictionary<int,int> suffixCount = new Dictionary<int,int>();
 
    // Stores the total sum of array
    int total = 0;
 
    // Traverse the array
    for (int i = N - 1; i >= 0; i--)
    {
 
      total += arr[i];
 
      // Increase the frequency of
      // current element in suffix
      if(suffixCount.ContainsKey(arr[i])){
        suffixCount[arr[i]] = suffixCount[arr[i]] + 1;
      }
      else{
        suffixCount.Add(arr[i], 1);
      }
    }
 
    // Stores prefix sum upto
    // an index
    int prefixSum = 0;
 
    // Stores sum of suffix
    // from an index
    int suffixSum = 0;
 
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    int count = 0;
 
    // Traverse the array
    for (int i = 0; i < N - 1; i++)
    {
 
      // Modify prefix sum
      prefixSum += arr[i];
 
      // Add arr[i] to prefix Map
      if(prefixCount.ContainsKey(arr[i]))
      {
        prefixCount[arr[i]] = prefixCount[arr[i]] + 1;
      }
      else
      {
        prefixCount.Add(arr[i], 1);
      }
 
      // Calculate suffix sum by
      // subtracting prefix sum
      // from total sum of elements
      suffixSum = total - prefixSum;
 
      // Remove arr[i] from suffix Map
      if(suffixCount.ContainsKey(arr[i]))
      {
        suffixCount[arr[i]] = suffixCount[arr[i]] - 1;
      }
 
      // Store the difference
      // between the subarrays
      int diff = prefixSum - suffixSum;
 
      // Check if diff is even or not
      if (diff % 2 == 0)
      {
 
        // Count number of ways to
        // split array at index i such
        // that subarray sums are same
        int x = (prefixCount.ContainsKey(diff / 2)?prefixCount:0)
          + (suffixCount.ContainsKey(-diff / 2)?suffixCount[-diff / 2]:0);
 
        // Update the count
        count = count + x;
      }
    }
 
    // Return the count
    return count;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int []arr = { 2, 2, -3, 3 };
    int N = arr.Length;
 
    // Function Call
    Console.Write(countSubArraySignChange(arr, N));
  }
}
 
 
// This code is contributed by 29AjayKumar




<script>
 
// JavaScript program for the above approach
 
// Function to count ways of splitting
// the array in two subarrays of equal
// sum by changing sign of any 1 element
function countSubArraySignChange(arr,N)
{
    // Stores the count of elements
    // in prefix and suffix of array
    let prefixCount = new Map();
    let suffixCount = new Map();
  
    // Stores the total sum of array
    let total = 0;
  
    // Traverse the array
    for (let i = N - 1; i >= 0; i--)
    {
  
        total += arr[i];
  
        // Increase the frequency of
        // current element in suffix
        if(suffixCount.has(arr[i])){
            suffixCount.set(arr[i], suffixCount.get(arr[i]) + 1);
        }
        else{
            suffixCount.set(arr[i], 1);
        }
    }
  
    // Stores prefix sum upto
    // an index
    let prefixSum = 0;
  
    // Stores sum of suffix
    // from an index
    let suffixSum = 0;
  
    // Stores the count of ways to
    // split the array in 2 subarrays
    // having equal sum
    let count = 0;
  
    // Traverse the array
    for (let i = 0; i < N - 1; i++)
    {
  
        // Modify prefix sum
        prefixSum += arr[i];
  
        // Add arr[i] to prefix Map
        if(prefixCount.has(arr[i]))
        {
            prefixCount.set(arr[i], prefixCount.get(arr[i])+1);
        }
        else
        {
            prefixCount.set(arr[i], 1);
        }
  
        // Calculate suffix sum by
        // subtracting prefix sum
        // from total sum of elements
        suffixSum = total - prefixSum;
  
        // Remove arr[i] from suffix Map
        if(suffixCount.has(arr[i]))
        {
            suffixCount.set(arr[i], suffixCount.get(arr[i]) - 1);
        }
  
        // Store the difference
        // between the subarrays
        let diff = prefixSum - suffixSum;
  
        // Check if diff is even or not
        if (diff % 2 == 0)
        {
  
            // Count number of ways to
            // split array at index i such
            // that subarray sums are same
            let x = (prefixCount.has(diff / 2)?
                     prefixCount.get(diff / 2):0)
                    + (suffixCount.has(-diff / 2)?
                       suffixCount.get(-diff / 2):0);
  
            // Update the count
            count = count + x;
        }
    }
  
    // Return the count
    return count;
}
 
// Driver Code
let arr=[2, 2, -3, 3];
let N = arr.length;
// Function Call
document.write(countSubArraySignChange(arr, N));
 
 
 
// This code is contributed by patel2127
 
</script>

Output: 
2

 

Time Complexity: O(N)
Auxiliary Space: O(N)

Related Topic: Subarrays, Subsequences, and Subsets in Array


Article Tags :