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: 4
Explanation:
Replacing arr[0] by 0, arr[] is modified to {0, 2, -1, 3}. Only 1 possible split is {0, 2} and {-1, 3}.
Replacing arr[1] by 0, arr[] is modified to {1, 0, -1, 3}. No way to split the array.
Replacing arr[2] by 0, arr[] is modified to {1, 2, 0, 3}. The 2 possible splits are {1, 2, 0} and {3}, {1, 2} and {0, 3}.
Replacing arr[3] by 0, arr[] is modified to {1, 2, -1, 0}. Only 1 possible split is {1} and {2, -1, 0}.
Therefore, the total number of ways to split = 1 + 0 + 2 + 1 = 4.
Input: arr[] = {1, 2, 1, 1, 3, 1}
Output: 6
Explanation:
Replacing arr[0] by 0, arr[] is modified to {0, 2, 1, 1, 3, 1}. Only 1 possible split exists.
Replacing arr[1] by 0, arr[] is modified to {1, 0, 1, 1, 3, 1}. No way to split the array.
Replacing arr[2] by 0, arr[] is modified to {1, 2, 0, 1, 3, 1}. Only 1 possible split exists.
Replacing arr[3] by 0, arr[] is modified to {1, 2, 1, 0, 3, 1}. Only 2 possible splits exist.
Replacing arr[4] by 0, arr[] is modified to {1, 2, 1, 1, 0, 1}. Only 1 possible split exists.
Replacing arr[5] by 0, arr[] is modified to {1, 2, 1, 1, 3, 0}. Only 1 possible split exists.
Total number of ways to split is = 1 + 0 + 1 + 2 + 1 + 1 = 6.
Naive Approach: The simplest approach to solve the problem is to traverse the array, convert each array element arr[i] to 0 and count the number of ways to split the modified array into two subarrays with equal sum.
Time Complexity: O(N2)
Auxiliary Space: O(1)
Efficient Approach: To optimize the above approach, the idea is based on the following observations:
Considering two arrays arr1[] and arr2[] with sum of the array elements equal to sum_arr1 and sum_arr2 respectively.
Let dif be the difference between sum_arr1 and sum_arr2, i.e., sum_arr1 – sum_arr2 = dif.
Now, sum_arr1 can be made equal to sum_arr2 by performing any one of the two operations:
- Remove an element from arr1[] whose value is equal to dif.
- Remove an element from arr2[] whose value is equal to -dif.
Therefore, the total number of ways to obtain sum_arr1 = sum_arr2 is equal to the count of dif in arr1 + count of (-dif) in arr2.
For every index in the range [0, N – 1], the total number of ways can be obtained by considering the current index as the splitting point, by making any element equal to 0 using the process discussed above. Follow the steps below to solve the problem:
- Initialize a variable count with 0 to store the desired result and prefix_sum the with 0 to store the prefix sum and suffixSum with 0 to store the suffix sum.
- Initialize hashmaps prefixCount and suffixCount to store the count of elements in prefix and suffix arrays.
- Traverse the arr[] and update the frequency of each element in suffixCount.
- Traverse the arr[] over the range [0, N – 1] using variable i.
- Add arr[i] to the prefixCount hashmap 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 a subarray in variable dif = prefix_sum – suffixSum.
- Store the number of ways to split at ith index in number_of_subarray_at_i_split and is equal to the sum of prefixCount and suffixCount.
- Update the count by adding number_of_subarray_at_i_split to it.
- After the above steps, print the value of count as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countSubArrayRemove( int arr[], int N)
{
unordered_map< int , int >
prefix_element_count,
suffix_element_count;
int total_sum_of_elements = 0;
for ( int i = N - 1; i >= 0; i--) {
total_sum_of_elements += arr[i];
suffix_element_count[arr[i]]++;
}
int prefix_sum = 0;
int suffix_sum = 0;
int count_subarray_equal_sum = 0;
for ( int i = 0; i < N; i++) {
prefix_sum += arr[i];
prefix_element_count[arr[i]]++;
suffix_sum = total_sum_of_elements
- prefix_sum;
suffix_element_count[arr[i]]--;
int difference = prefix_sum
- suffix_sum;
int number_of_subarray_at_i_split
= prefix_element_count[difference]
+ suffix_element_count[-difference];
count_subarray_equal_sum
+= number_of_subarray_at_i_split;
}
return count_subarray_equal_sum;
}
int main()
{
int arr[] = { 1, 2, 1, 1, 3, 1 };
int N = sizeof (arr) / sizeof (arr[0]);
cout << countSubArrayRemove(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countSubArrayRemove( int []arr, int N)
{
HashMap<Integer,
Integer> prefix_element_count = new HashMap<Integer,
Integer>();
HashMap<Integer,
Integer> suffix_element_count = new HashMap<Integer,
Integer>();
int total_sum_of_elements = 0 ;
for ( int i = N - 1 ; i >= 0 ; i--)
{
total_sum_of_elements += arr[i];
if (!suffix_element_count.containsKey(arr[i]))
suffix_element_count.put(arr[i], 1 );
else
suffix_element_count.put(arr[i],
suffix_element_count.get(arr[i]) + 1 );
}
int prefix_sum = 0 ;
int suffix_sum = 0 ;
int count_subarray_equal_sum = 0 ;
for ( int i = 0 ; i < N; i++)
{
prefix_sum += arr[i];
if (!prefix_element_count.containsKey(arr[i]))
prefix_element_count.put(arr[i], 1 );
else
prefix_element_count.put(arr[i],
prefix_element_count.get(arr[i]) + 1 );
suffix_sum = total_sum_of_elements -
prefix_sum;
if (!suffix_element_count.containsKey(arr[i]))
suffix_element_count.put(arr[i], 0 );
else
suffix_element_count.put(arr[i],
suffix_element_count.get(arr[i]) - 1 );
int difference = prefix_sum -
suffix_sum;
int number_of_subarray_at_i_split = 0 ;
if (prefix_element_count.containsKey(difference))
number_of_subarray_at_i_split =
prefix_element_count.get(difference);
if (suffix_element_count.containsKey(-difference))
number_of_subarray_at_i_split +=
suffix_element_count.get(-difference);
count_subarray_equal_sum +=
number_of_subarray_at_i_split;
}
return count_subarray_equal_sum;
}
public static void main(String args[])
{
int []arr = { 1 , 2 , 1 , 1 , 3 , 1 };
int N = arr.length;
System.out.println(countSubArrayRemove(arr, N));
}
}
|
Python3
def countSubArrayRemove(arr, N):
prefix_element_count = {}
suffix_element_count = {}
total_sum_of_elements = 0
i = N - 1
while (i > = 0 ):
total_sum_of_elements + = arr[i]
suffix_element_count[arr[i]] = suffix_element_count.get(
arr[i], 0 ) + 1
i - = 1
prefix_sum = 0
suffix_sum = 0
count_subarray_equal_sum = 0
for i in range (N):
prefix_sum + = arr[i]
prefix_element_count[arr[i]] = prefix_element_count.get(
arr[i], 0 ) + 1
suffix_sum = total_sum_of_elements - prefix_sum
suffix_element_count[arr[i]] = suffix_element_count.get(
arr[i], 0 ) - 1
difference = prefix_sum - suffix_sum
number_of_subarray_at_i_split = (prefix_element_count.get(
difference, 0 ) +
suffix_element_count.get(
- difference, 0 ))
count_subarray_equal_sum + = number_of_subarray_at_i_split
return count_subarray_equal_sum
if __name__ = = '__main__' :
arr = [ 1 , 2 , 1 , 1 , 3 , 1 ]
N = len (arr)
print (countSubArrayRemove(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int countSubArrayRemove( int []arr, int N)
{
Dictionary< int ,
int > prefix_element_count = new Dictionary< int ,
int > ();
Dictionary< int ,
int >suffix_element_count = new Dictionary < int ,
int >();
int total_sum_of_elements = 0;
for ( int i = N - 1; i >= 0; i--)
{
total_sum_of_elements += arr[i];
if (!suffix_element_count.ContainsKey(arr[i]))
suffix_element_count[arr[i]] = 1;
else
suffix_element_count[arr[i]]++;
}
int prefix_sum = 0;
int suffix_sum = 0;
int count_subarray_equal_sum = 0;
for ( int i = 0; i < N; i++)
{
prefix_sum += arr[i];
if (!prefix_element_count.ContainsKey(arr[i]))
prefix_element_count[arr[i]] = 1;
else
prefix_element_count[arr[i]]++;
suffix_sum = total_sum_of_elements -
prefix_sum;
if (!suffix_element_count.ContainsKey(arr[i]))
suffix_element_count[arr[i]] = 0;
else
suffix_element_count[arr[i]]-= 1;
int difference = prefix_sum -
suffix_sum;
int number_of_subarray_at_i_split = 0;
if (prefix_element_count.ContainsKey(difference))
number_of_subarray_at_i_split
= prefix_element_count[difference];
if (suffix_element_count.ContainsKey(-difference))
number_of_subarray_at_i_split
+= suffix_element_count[-difference];
count_subarray_equal_sum
+= number_of_subarray_at_i_split;
}
return count_subarray_equal_sum;
}
public static void Main( string []args)
{
int []arr = { 1, 2, 1, 1, 3, 1 };
int N = arr.Length;
Console.Write(countSubArrayRemove(arr, N));
}
}
|
Javascript
<script>
function countSubArrayRemove(arr, N)
{
let prefix_element_count = new Map();
let suffix_element_count = new Map();
let total_sum_of_elements = 0;
for (let i = N - 1; i >= 0; i--)
{
total_sum_of_elements += arr[i];
if (!suffix_element_count.has(arr[i]))
suffix_element_count.set(arr[i], 1);
else
suffix_element_count.set(arr[i],
suffix_element_count.get(arr[i]) + 1);
}
let prefix_sum = 0;
let suffix_sum = 0;
let count_subarray_equal_sum = 0;
for (let i = 0; i < N; i++)
{
prefix_sum += arr[i];
if (!prefix_element_count.has(arr[i]))
prefix_element_count.set(arr[i], 1);
else
prefix_element_count.set(arr[i],
prefix_element_count.get(arr[i]) + 1);
suffix_sum = total_sum_of_elements -
prefix_sum;
if (!suffix_element_count.has(arr[i]))
suffix_element_count.set(arr[i], 0);
else
suffix_element_count.set(arr[i],
suffix_element_count.get(arr[i]) - 1);
let difference = prefix_sum -
suffix_sum;
let number_of_subarray_at_i_split = 0;
if (prefix_element_count.has(difference))
number_of_subarray_at_i_split =
prefix_element_count.get(difference);
if (suffix_element_count.has(-difference))
number_of_subarray_at_i_split +=
suffix_element_count.get(-difference);
count_subarray_equal_sum +=
number_of_subarray_at_i_split;
}
return count_subarray_equal_sum;
}
let arr = [ 1, 2, 1, 1, 3, 1 ];
let N = arr.length;
document.write(countSubArrayRemove(arr, N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Last Updated :
15 Jun, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...