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:
- 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 spliting # 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> |
2
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Topic: Subarrays, Subsequences, and Subsets in Array
Please Login to comment...