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[diff 1="2" language="/"][/diff] + 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[diff / 2]
+ 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[diff/2]
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[diff / 2]: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>
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}.
11 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 min read
Print indices of pair of array elements required to be removed to split array into 3 equal sum subarrays
Given an array arr[] consisting of N integers, the task is to print the indices of two array elements required to be removed such that the given array can be split into three subarrays of equal sum. If not possible to do so, then print "-1". Examples: Input: arr[] = {2, 5, 12, 7, 19, 4, 3}Output: 2
15+ 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: { {{
8 min read
Count ways to split array into pair of subsets with difference between their sum equal to K
Given an array arr[] consisting of N integers and an integer K, the task is to find the number of ways to split the array into a pair of subsets such that the difference between their sum is K. Examples: Input: arr[] = {1, 1, 2, 3}, K = 1Output: 3Explanation:Following splits into a pair of subsets s
15 min read
Find an element in array such that sum of left array is equal to sum of right array
Given, an array of size n. Find an element that divides the array into two sub-arrays with equal sums. Examples: Input: 1 4 2 5 0Output: 2Explanation: If 2 is the partition, subarrays are : [1, 4] and [5] Input: 2 3 4 1 4 5Output: 1Explanation: If 1 is the partition, Subarrays are : [2, 3, 4] and [4
15+ 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},
9 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
15 min read
Partition an array into two subsets with equal count of unique elements
Given an array arr[] consisting of N integers, the task is to partition the array into two subsets such that the count of unique elements in both the subsets is the same and for each element, print 1 if that element belongs to the first subset. Otherwise, print 2. If it is not possible to do such a
13 min read
Number of ways to divide an array into K equal sum sub-arrays
Given an integer K and an array arr[] of N integers, the task is to find the number of ways to split the array into K equal sum sub-arrays of non-zero lengths. Examples: Input: arr[] = {0, 0, 0, 0}, K = 3 Output: 3 All possible ways are: {{0}, {0}, {0, 0}} {{0}, {0, 0}, {0}} {{0, 0}, {0}, {0}}Input:
9 min read