Count ways to split array into two equal sum subarrays by changing sign of any one array element
Last Updated :
18 Apr, 2023
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++
#include <bits/stdc++.h>
using namespace std;
int countSubArraySignChange( int arr[], int N)
{
unordered_map< int , int > prefixCount;
unordered_map< int , int > suffixCount;
int total = 0;
for ( int i = N - 1; i >= 0; i--) {
total += arr[i];
suffixCount[arr[i]]++;
}
int prefixSum = 0;
int suffixSum = 0;
int count = 0;
for ( int i = 0; i < N - 1; i++) {
prefixSum += arr[i];
prefixCount[arr[i]]++;
suffixSum = total - prefixSum;
suffixCount[arr[i]]--;
int diff = prefixSum - suffixSum;
if (diff % 2 == 0) {
int x = prefixCount
+ suffixCount[-diff / 2];
count = count + x;
}
}
return count;
}
int main()
{
int arr[] = { 2, 2, -3, 3 };
int N = sizeof (arr) / sizeof (arr[0]);
cout << countSubArraySignChange(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countSubArraySignChange( int arr[], int N)
{
HashMap<Integer,Integer> prefixCount = new HashMap<Integer,Integer>();
HashMap<Integer,Integer> suffixCount = new HashMap<Integer,Integer>();
int total = 0 ;
for ( int i = N - 1 ; i >= 0 ; i--)
{
total += arr[i];
if (suffixCount.containsKey(arr[i])){
suffixCount.put(arr[i], suffixCount.get(arr[i]) + 1 );
}
else {
suffixCount.put(arr[i], 1 );
}
}
int prefixSum = 0 ;
int suffixSum = 0 ;
int count = 0 ;
for ( int i = 0 ; i < N - 1 ; i++)
{
prefixSum += arr[i];
if (prefixCount.containsKey(arr[i]))
{
prefixCount.put(arr[i], prefixCount.get(arr[i])+ 1 );
}
else
{
prefixCount.put(arr[i], 1 );
}
suffixSum = total - prefixSum;
if (suffixCount.containsKey(arr[i]))
{
suffixCount.put(arr[i], suffixCount.get(arr[i]) - 1 );
}
int diff = prefixSum - suffixSum;
if (diff % 2 == 0 )
{
int x = (prefixCount.containsKey(diff / 2 )?prefixCount.get(diff / 2 ): 0 )
+ (suffixCount.containsKey(-diff / 2 )?suffixCount.get(-diff / 2 ): 0 );
count = count + x;
}
}
return count;
}
public static void main(String[] args)
{
int arr[] = { 2 , 2 , - 3 , 3 };
int N = arr.length;
System.out.print(countSubArraySignChange(arr, N));
}
}
|
Python3
def countSubArraySignChange(arr, N):
prefixCount = {}
suffixCount = {}
total = 0
for i in range (N - 1 , - 1 , - 1 ):
total + = arr[i]
suffixCount[arr[i]] = suffixCount.get(arr[i], 0 ) + 1
prefixSum = 0
suffixSum = 0
count = 0
for i in range (N - 1 ):
prefixSum + = arr[i]
prefixCount[arr[i]] = prefixCount.get(arr[i], 0 ) + 1
suffixSum = total - prefixSum
suffixCount[arr[i]] - = 1
diff = prefixSum - suffixSum
if (diff % 2 = = 0 ):
y, z = 0 , 0
if - diff / / 2 in suffixCount:
y = suffixCount[ - dff / / 2 ]
if diff / / 2 in prefixCount:
z = prefixCount
x = z + y
count = count + x
return count
if __name__ = = '__main__' :
arr = [ 2 , 2 , - 3 , 3 ]
N = len (arr)
print (countSubArraySignChange(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int countSubArraySignChange( int []arr, int N)
{
Dictionary< int , int > prefixCount = new Dictionary< int , int >();
Dictionary< int , int > suffixCount = new Dictionary< int , int >();
int total = 0;
for ( int i = N - 1; i >= 0; i--)
{
total += arr[i];
if (suffixCount.ContainsKey(arr[i])){
suffixCount[arr[i]] = suffixCount[arr[i]] + 1;
}
else {
suffixCount.Add(arr[i], 1);
}
}
int prefixSum = 0;
int suffixSum = 0;
int count = 0;
for ( int i = 0; i < N - 1; i++)
{
prefixSum += arr[i];
if (prefixCount.ContainsKey(arr[i]))
{
prefixCount[arr[i]] = prefixCount[arr[i]] + 1;
}
else
{
prefixCount.Add(arr[i], 1);
}
suffixSum = total - prefixSum;
if (suffixCount.ContainsKey(arr[i]))
{
suffixCount[arr[i]] = suffixCount[arr[i]] - 1;
}
int diff = prefixSum - suffixSum;
if (diff % 2 == 0)
{
int x = (prefixCount.ContainsKey(diff / 2)?prefixCount:0)
+ (suffixCount.ContainsKey(-diff / 2)?suffixCount[-diff / 2]:0);
count = count + x;
}
}
return count;
}
public static void Main(String[] args)
{
int []arr = { 2, 2, -3, 3 };
int N = arr.Length;
Console.Write(countSubArraySignChange(arr, N));
}
}
|
Javascript
<script>
function countSubArraySignChange(arr,N)
{
let prefixCount = new Map();
let suffixCount = new Map();
let total = 0;
for (let i = N - 1; i >= 0; i--)
{
total += arr[i];
if (suffixCount.has(arr[i])){
suffixCount.set(arr[i], suffixCount.get(arr[i]) + 1);
}
else {
suffixCount.set(arr[i], 1);
}
}
let prefixSum = 0;
let suffixSum = 0;
let count = 0;
for (let i = 0; i < N - 1; i++)
{
prefixSum += arr[i];
if (prefixCount.has(arr[i]))
{
prefixCount.set(arr[i], prefixCount.get(arr[i])+1);
}
else
{
prefixCount.set(arr[i], 1);
}
suffixSum = total - prefixSum;
if (suffixCount.has(arr[i]))
{
suffixCount.set(arr[i], suffixCount.get(arr[i]) - 1);
}
let diff = prefixSum - suffixSum;
if (diff % 2 == 0)
{
let x = (prefixCount.has(diff / 2)?
prefixCount.get(diff / 2):0)
+ (suffixCount.has(-diff / 2)?
suffixCount.get(-diff / 2):0);
count = count + x;
}
}
return count;
}
let arr=[2, 2, -3, 3];
let N = arr.length;
document.write(countSubArraySignChange(arr, N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Topic: Subarrays, Subsequences, and Subsets in Array
Please Login to comment...