Open In App

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

Last Updated : 18 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  • Initialize a variable, say count, to store the number of ways to split the array.
  • Initialize two variables, say prefixSum and suffixSum, with 0, to store the prefix and suffix sums of both the arrays.
  • Initialize two Maps prefixCount and suffixCount to store the count of elements in prefix and suffix arrays.
  • Traverse the array arr[] and update the frequency of each element in suffixCount.
  • Traverse the array arr[] and perform the following steps:
    • Insert arr[i] into the prefixCount map and remove it from suffixCount.
    • Add arr[i] to prefixSum and set suffixSum to the difference of the total sum of the array and prefixSum.
    • Store the difference between the sum of the subarrays, i.e. prefixSum – suffixSum in a variable, say diff.
    • The count of ways to split at the ith index is calculated by:
      • If diff is odd, then the array cannot be split.
      • If diff is even, then add the value (prefixCount + suffixCount[ -diff / 2]) to count.
  • After completing the above steps, the value of count gives the total count of possible splits.

Below is the implementation of the above approach:

C++




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




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




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




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


Javascript




<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



Similar Reads

Count ways to split array into two equal sum subarrays by replacing each array element to 0 once
Given an array arr[] consisting of N integers, the task is to count the number of ways to split the array into two subarrays of equal sum after changing a single array element to 0. Examples: Input: arr[] = {1, 2, -1, 3}Output: 4Explanation: Replacing arr[0] by 0, arr[] is modified to {0, 2, -1, 3}. Only 1 possible split is {0, 2} and {-1, 3}. Repl
11 min read
Count ways to split array into two subarrays with equal GCD
Given an array, arr[] of size N, the task is to count the number of ways to split given array elements into two subarrays such that GCD of both the subarrays are equal. Examples: Input: arr[] = {8, 4, 4, 8, 12} Output: 2 Explanation: Possible ways to split the array two groups of equal GCD are: { {{arr[0], arr[1]}, {arr[2], arr[3], arr[4]}}, {{arr[
8 min read
Minimum length of a rod that can be split into N equal parts that can further be split into given number of equal parts
Given an array arr[] consisting of N positive integers, the task is to find the minimum possible length of a rod that can be cut into N equal parts such that every ith part can be cut into arr[i] equal parts. Examples: Input: arr[] = {1, 2}Output: 4Explanation:Consider the length of the rod as 4. Then it can be divided in 2 equal parts, each having
7 min read
Count ways to split array into three non-empty subarrays having equal Bitwise XOR values
Given an array arr[] consisting of N non-negative integers, the task is to count the number of ways to split the array into three different non-empty subarrays such that Bitwise XOR of each subarray is equal. Examples: Input: arr[] = {7, 0, 5, 2, 7} Output: 2Explanation: All possible ways are:{{7}, {0, 5, 2}, {7}} where XOR value of each subarray i
9 min read
Maximize Array sum after changing sign of any elements for exactly M times
Given an array arr[] of size N and an integer M, the task is to find the maximum sum of the array after changing the sign of any elements in the array for exactly M times. It is allowed to change the sign of the same element multiple times. Examples: Input: arr[ ] = {-3, 7, -1, -5, -3}, M = 4Output: 19Explanation:4 operations on the array can be pe
6 min read
Count ways to split array into two subsets having difference between their sum equal to K
Given an array A[] of size N and an integer diff, the task is to count the number of ways to split the array into two subsets (non-empty subset is possible) such that the difference between their sums is equal to diff. Examples: Input: A[] = {1, 1, 2, 3}, diff = 1 Output: 3 Explanation: All possible combinations are as follows: {1, 1, 2} and {3}{1,
14 min read
Count of ways to split an Array into three contiguous Subarrays having increasing Sum
Given an array arr[] consisting of non-negative integers, the task is to find the number of ways to split the array into three non-empty contiguous subarrays such that their respective sum of elements are in increasing order. Examples: Input: arr[] = {2, 3, 1, 7} Output: 2 Explanation: {{2}, {3, 1}, {7}}, {{2}, {3}, {1, 7}} are the possible splits.
7 min read
Count ways to split an array into subarrays such that sum of the i-th subarray is divisible by i
Given an array arr[] consisting of N integers, the task is to find the number of ways to split the array into non-empty subarrays such that the sum of the ith subarray is divisible by i. Examples: Input: arr[] = {1, 2, 3, 4}Output: 3Explanation:Following are the number of ways to split the array into non-empty subarray as: Split the array into suba
8 min read
Split an array into two equal Sum subarrays
Given an array of integers greater than zero, find if it is possible to split it in two subarrays (without reordering the elements), such that the sum of the two subarrays is the same. Print the two subarrays. Examples : Input : Arr[] = { 1 , 2 , 3 , 4 , 5 , 5 } Output : { 1 2 3 4 } { 5 , 5 } Input : Arr[] = { 4, 1, 2, 3 } Output : {4 1} {2 3} Inpu
15 min read
Split array into K subarrays such that sum of maximum of all subarrays is maximized
Given an array arr[] of size N and a number K, the task is to partition the given array into K contiguous subarrays such that the sum of the maximum of each subarray is the maximum possible. If it is possible to split the array in such a manner, then print the maximum possible sum. Otherwise, print "-1". Examples: Input: arr[] = {5, 3, 2, 7, 6, 4},
11 min read