Count the number of ways to divide an array into three contiguous parts having equal sum
Given an array of n numbers. Our task is to find out the number of ways to divide the array into three contiguous parts such that the sum of three parts is equal. In other words, we need to find the number of index pairs i and j such that sum of elements from 0 to i-1 is equal to the sum of elements from i to j is equal to the sum of elements from j+1 to n-1.
Examples:
Input : arr[] = {1, 2, 3, 0, 3}
Output : 2
Following are two possible ways to partition
1) Three parts are (1, 2), (3) and (0, 3)
2) Three parts are (1, 2), (3,0) and (3)
Input : arr[] = {0, 1, -1, 0}
Output : 1
It is only one way to partition.
1) Three parts are (0), (1,-1) and (0)
Naive Approach
The idea is to find every possible index pair i and j such that array can be divided into three parts. Then find the sum of each part and if the sum of all three part are equal then increment the count
Steps to implement-
- Initialize a variable count with a value of 0.
- Now run two nested for loops to choose index i and j such that we will get three parts of array
- After that initialize three variables with a value of 0 to find the sum of those three part
- Run a for loop from 0 to i-1 to find the sum of the first part
- Run a for loop from i to j to find the sum of the second part
- Run a for loop from j+1 to n-1 to find the sum of the third part
- When the sum of all three parts becomes equal then increment the count
- In last return or print the count variable
Code-
C++
#include <bits/stdc++.h>
using namespace std;
int CountContiguousParts( int arr[], int n)
{
int count = 0;
for ( int i=1;i<n-1;i++){
for ( int j=i;j<n-1;j++){
int sum1=0;
int sum2=0;
int sum3=0;
for ( int k=0;k<i;k++){
sum1+=arr[k];
}
for ( int k=i;k<=j;k++){
sum2+=arr[k];
}
for ( int k=j+1;k<n;k++){
sum3+=arr[k];
}
if (sum1==sum2 && sum2==sum3 && sum1==sum3){
count++;
}
}
}
return count;
}
int main()
{
int arr[] = { 1, 2, 3, 0, 3 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << CountContiguousParts(arr, n);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int countContiguousParts( int [] arr, int n) {
int count = 0 ;
for ( int i= 1 ;i<n- 1 ;i++){
for ( int j=i;j<n- 1 ;j++){
int sum1= 0 ;
int sum2= 0 ;
int sum3= 0 ;
for ( int k= 0 ;k<i;k++){
sum1+=arr[k];
}
for ( int k=i;k<=j;k++){
sum2+=arr[k];
}
for ( int k=j+ 1 ;k<n;k++){
sum3+=arr[k];
}
if (sum1==sum2 && sum2==sum3 && sum1==sum3){
count++;
}
}
}
return count;
}
public static void main(String[] args) {
int arr[] = { 1 , 2 , 3 , 0 , 3 };
int n = arr.length;
System.out.println(countContiguousParts(arr, n));
}
}
|
Python
def count_contiguous_parts(arr):
count = 0
n = len (arr)
for i in range ( 1 , n - 1 ):
for j in range (i, n - 1 ):
sum1, sum2, sum3 = 0 , 0 , 0
for k in range ( 0 , i):
sum1 + = arr[k]
for k in range (i, j + 1 ):
sum2 + = arr[k]
for k in range (j + 1 , n):
sum3 + = arr[k]
if sum1 = = sum2 and sum2 = = sum3 and sum1 = = sum3:
count + = 1
return count
if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 , 0 , 3 ]
print (count_contiguous_parts(arr))
|
C#
using System;
class Program
{
static int CountContiguousParts( int [] arr, int n)
{
int count = 0;
for ( int i = 1; i < n - 1; i++)
{
for ( int j = i; j < n - 1; j++)
{
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
for ( int k = 0; k < i; k++)
{
sum1 += arr[k];
}
for ( int k = i; k <= j; k++)
{
sum2 += arr[k];
}
for ( int k = j + 1; k < n; k++)
{
sum3 += arr[k];
}
if (sum1 == sum2 && sum2 == sum3 && sum1 == sum3)
{
count++;
}
}
}
return count;
}
static void Main( string [] args)
{
int [] arr = { 1, 2, 3, 0, 3 };
int n = arr.Length;
Console.WriteLine(CountContiguousParts(arr, n));
}
}
|
Javascript
function CountContiguousParts(arr) {
let count = 0;
for (let i = 1; i < arr.length - 1; i++) {
for (let j = i; j < arr.length - 1; j++) {
let sum1 = 0;
let sum2 = 0;
let sum3 = 0;
for (let k = 0; k < i; k++) {
sum1 += arr[k];
}
for (let k = i; k <= j; k++) {
sum2 += arr[k];
}
for (let k = j + 1; k < arr.length; k++) {
sum3 += arr[k];
}
if (sum1 === sum2 && sum2 === sum3 && sum1 === sum3) {
count++;
}
}
}
return count;
}
const arr = [1, 2, 3, 0, 3];
console.log(CountContiguousParts(arr));
|
Time Complexity: O(N3), because of two nested loops to find i and j, then loops to find the sum of all three parts
Auxiliary Space: O(1), because no extra space has been used
Another Approach
If the sum of all the elements of the array is not divisible by 3 return 0. Else it is obvious that the sum of each part of each contiguous part will be equal to the sum of all elements divided by 3.
- Step 1 : Create an array of the same size as a given array whose i-th index holds the value of the sum of elements from indices 0 to i of the given array. Let’s call it prefix array
- Step 2 : Create another array of the same size as a given array whose i-th index the value of sum of elements from indices i to n-1 of the given array. Let’s call it suffix array.
- Step 3 : The idea is simple, we start traversing the prefix array and suppose at the i-th index of the prefix array the value of prefix array is equal to (sum of all elements of given array)/3.
- Step 4 : For i found in the above step we look into the suffix array from (i+2)-th index and wherever the value of suffix array is equal to (sum of all elements of given array)/3, we increase the counter variable by 1.
To implement step 4 we traverse suffix array and wherever the value of suffix array is equal to the sum of all elements of given array/3 we push that index of suffix array into the vector. And we do a binary search in the vector to calculate the number of values in suffix array which are as according to step 4.
We search in suffix array because there should be at least 1 element between the first and third part.
For more explanation see implementation below:
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int binarysearch(vector< int >& v, int x)
{
int low = 0, high = v.size() - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (v[mid] <= x)
low = mid + 1;
else if (v[mid] > x && v[mid - 1] <= x)
return mid;
else if (v[mid] > x && mid == 0)
return mid;
else
high = mid - 1;
}
return -1;
}
int CountContiguousParts( int arr[], int n)
{
int count = 0;
int prefix[n];
prefix[0] = arr[0];
for ( int i = 1; i < n; i++)
prefix[i] = prefix[i - 1] + arr[i];
int total_sum = prefix[n - 1];
if (total_sum % 3 != 0)
return 0;
int suffix[n];
suffix[n - 1] = arr[n - 1];
for ( int i = n - 2; i >= 0; i--)
suffix[i] = suffix[i + 1] + arr[i];
vector< int > v;
for ( int i = 0; i < n; i++)
if (suffix[i] == total_sum / 3)
v.push_back(i);
for ( int i = 0; i < n; i++) {
if (prefix[i] == total_sum / 3) {
int res = binarysearch(v, i + 1);
if (res != -1)
count += v.size() - res;
}
}
return count;
}
int main()
{
int arr[] = { 1, 2, 3, 0, 3 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << CountContiguousParts(arr, n);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int binarysearch(Vector<Integer> v, int x)
{
int low = 0 , high = v.size() - 1 ;
while (low <= high) {
int mid = (low + high) / 2 ;
if (v.get(mid) <= x)
low = mid + 1 ;
else if (v.get(mid) > x && v.get(mid) <= x)
return mid;
else if (v.get(mid) > x && mid == 0 )
return mid;
else
high = mid - 1 ;
}
return - 1 ;
}
static int CountContiguousParts( int arr[], int n)
{
int count = 0 ;
int [] prefix = new int [n];
prefix[ 0 ] = arr[ 0 ];
for ( int i = 1 ; i < n; i++)
prefix[i] = prefix[i - 1 ] + arr[i];
int total_sum = prefix[n - 1 ];
if (total_sum % 3 != 0 )
return 0 ;
int [] suffix = new int [n];
suffix[n - 1 ] = arr[n - 1 ];
for ( int i = n - 2 ; i >= 0 ; i--)
suffix[i] = suffix[i + 1 ] + arr[i];
Vector<Integer> v = new Vector<>();
for ( int i = 0 ; i < n; i++)
if (suffix[i] == total_sum / 3 )
v.add(i);
for ( int i = 0 ; i < n; i++) {
if (prefix[i] == total_sum / 3 ) {
int res = binarysearch(v, i + 1 );
if (res != - 1 )
count += v.size() - res;
}
}
return count;
}
public static void main(String[] args)
{
int arr[] = { 1 , 2 , 3 , 0 , 3 };
int n = arr.length;
System.out.println(CountContiguousParts(arr, n));
}
}
|
Python3
def binarysearch(v, x):
low = 0
high = len (v) - 1
while (low < = high):
mid = int ((low + high) / 2 )
if (v[mid] < = x):
low = mid + 1
elif (v[mid] > x and v[mid - 1 ] < = x):
return mid
elif (v[mid] > x and mid = = 0 ):
return mid
else :
high = mid - 1
return - 1
def CountContiguousParts(arr, n):
count = 0
prefix = [ 0 for i in range (n)]
prefix[ 0 ] = arr[ 0 ]
for i in range ( 1 , n, 1 ):
prefix[i] = prefix[i - 1 ] + arr[i]
total_sum = prefix[n - 1 ]
if (total_sum % 3 ! = 0 ):
return 0
suffix = [ 0 for i in range (n)]
suffix[n - 1 ] = arr[n - 1 ]
i = n - 2
while (i > = 0 ):
suffix[i] = suffix[i + 1 ] + arr[i]
i - = 1
v = []
for i in range (n):
if (suffix[i] = = int (total_sum / 3 )):
v.append(i)
for i in range (n):
if (prefix[i] = = int (total_sum / 3 )):
res = binarysearch(v, i + 1 )
if (res ! = - 1 ):
count + = len (v) - res
return count
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 , 0 , 3 ]
n = len (arr)
print (CountContiguousParts(arr, n))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int binarysearch(List< int > v, int x)
{
int low = 0, high = v.Count - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (v[mid] <= x)
low = mid + 1;
else if (v[mid] > x && v[mid] <= x)
return mid;
else if (v[mid] > x && mid == 0)
return mid;
else
high = mid - 1;
}
return -1;
}
static int CountContiguousParts( int [] arr, int n)
{
int count = 0;
int [] prefix = new int [n];
prefix[0] = arr[0];
for ( int i = 1; i < n; i++)
prefix[i] = prefix[i - 1] + arr[i];
int total_sum = prefix[n - 1];
if (total_sum % 3 != 0)
return 0;
int [] suffix = new int [n];
suffix[n - 1] = arr[n - 1];
for ( int i = n - 2; i >= 0; i--)
suffix[i] = suffix[i + 1] + arr[i];
List< int > v = new List< int >();
for ( int i = 0; i < n; i++)
if (suffix[i] == total_sum / 3)
v.Add(i);
for ( int i = 0; i < n; i++) {
if (prefix[i] == total_sum / 3) {
int res = binarysearch(v, i + 1);
if (res != -1)
count += v.Count - res;
}
}
return count;
}
public static void Main(String[] args)
{
int [] arr = { 1, 2, 3, 0, 3 };
int n = arr.Length;
Console.WriteLine(CountContiguousParts(arr, n));
}
}
|
Javascript
<script>
function binarysearch(v, x)
{
let low = 0, high = v.length - 1;
while (low <= high)
{
let mid = Math.floor((low + high) / 2);
if (v[mid] <= x)
low = mid + 1;
else if (v[mid] > x && v[mid] <= x)
return mid;
else if (v[mid] > x && mid == 0)
return mid;
else
high = mid - 1;
}
return -1;
}
function CountContiguousParts(arr, n)
{
let count = 0;
let prefix = new Array(n);
prefix[0] = arr[0];
for (let i = 1; i < n; i++)
prefix[i] = prefix[i - 1] + arr[i];
let total_sum = prefix[n - 1];
if (total_sum % 3 != 0)
return 0;
let suffix = new Array(n);
suffix[n - 1] = arr[n - 1];
for (let i = n - 2; i >= 0; i--)
suffix[i] = suffix[i + 1] + arr[i];
let v = [];
for (let i = 0; i < n; i++)
if (suffix[i] == Math.floor(total_sum / 3))
v.push(i);
for (let i = 0; i < n; i++)
{
if (prefix[i] == Math.floor(total_sum / 3))
{
let res = binarysearch(v, i + 1);
if (res != -1)
count += v.length - res;
}
}
return count;
}
let arr = [ 1 , 2 , 3 , 0 , 3 ];
let n = arr.length;
document.write(CountContiguousParts(arr, n));
</script>
|
Time Complexity is O(n log n)
Auxiliary Space: O(n)
Efficient Approach [ O(n) solution ] :
- If sum of all the elements of the array is not divisible by 3, return 0.
- It is obvious that the sum of each part of each contiguous part will be equal to the sum of all elements divided by 3.
- Let’s create an array cnt[ ], where cnt[ i ] equals 1, if the sum of elements from i-th to n-th equals Array_Sum/3 else 0. Now, calculate the cumulative sum of the cnt array from the last index.
- Thus, we receive very simple solution: for each prefix of initial array 1…i with the sum that equals Array_Sum/3 we need to add to the answer sums[ i+2].
Below is the code for the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int countways( int a[], int n)
{
int cnt[n] = { 0 }, s = 0;
for ( int i = 0; i < n; i++) {
s += a[i];
}
if (s % 3 != 0)
return 0;
s /= 3;
int ss = 0;
for ( int i = n - 1; i >= 0; i--) {
ss += a[i];
if (ss == s)
cnt[i] = 1;
}
for ( int i = n - 2; i >= 0; i--)
cnt[i] += cnt[i + 1];
int ans = 0;
ss = 0;
for ( int i = 0; i + 2 < n; i++) {
ss += a[i];
if (ss == s)
ans += cnt[i + 2];
}
return ans;
}
int main()
{
int n = 5;
int a[] = { 1, 2, 3, 0, 3 };
cout << countways(a, n) << endl;
return 0;
}
|
C
#include <bits/stdc++.h>
using namespace std;
int countways( int a[], int n)
{
int cnt[n] = { 0 }, s = 0;
for ( int i = 0; i < n; i++) {
s += a[i];
}
if (s % 3 != 0)
return 0;
s /= 3;
int ss = 0;
for ( int i = n - 1; i >= 0; i--) {
ss += a[i];
if (ss == s)
cnt[i] = 1;
}
for ( int i = n - 2; i >= 0; i--)
cnt[i] += cnt[i + 1];
int ans = 0;
ss = 0;
for ( int i = 0; i + 2 < n; i++) {
ss += a[i];
if (ss == s)
ans += cnt[i + 2];
}
return ans;
}
int main()
{
int n = 5;
int a[] = { 1, 2, 3, 0, 3 };
cout << countways(a, n) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int countways( int a[], int n)
{
int cnt[] = new int [n];
int s = 0 ;
for ( int i = 0 ; i < n; i++) {
s += a[i];
}
if (s % 3 != 0 )
return 0 ;
s /= 3 ;
int ss = 0 ;
for ( int i = n - 1 ; i >= 0 ; i--) {
ss += a[i];
if (ss == s)
cnt[i] = 1 ;
}
for ( int i = n - 2 ; i >= 0 ; i--)
cnt[i] += cnt[i + 1 ];
int ans = 0 ;
ss = 0 ;
for ( int i = 0 ; i + 2 < n; i++) {
ss += a[i];
if (ss == s)
ans += cnt[i + 2 ];
}
return ans;
}
public static void main(String[] args)
{
int n = 5 ;
int a[] = { 1 , 2 , 3 , 0 , 3 };
System.out.println(countways(a, n));
}
}
|
Python3
def countways(a, n):
cnt = [ 0 for i in range (n)]
s = 0
s = sum (a)
if (s % 3 ! = 0 ):
return 0
s / / = 3
ss = 0
for i in range (n - 1 , - 1 , - 1 ):
ss + = a[i]
if (ss = = s):
cnt[i] = 1
for i in range (n - 2 , - 1 , - 1 ):
cnt[i] + = cnt[i + 1 ]
ans = 0
ss = 0
for i in range ( 0 , n - 2 ):
ss + = a[i]
if (ss = = s):
ans + = cnt[i + 2 ]
return ans
n = 5
a = [ 1 , 2 , 3 , 0 , 3 ]
print (countways(a, n))
|
C#
using System;
class GFG {
static int countways( int [] a, int n)
{
int [] cnt = new int [n];
int s = 0;
for ( int i = 0; i < n; i++) {
s += a[i];
}
if (s % 3 != 0)
return 0;
s /= 3;
int ss = 0;
for ( int i = n - 1; i >= 0; i--) {
ss += a[i];
if (ss == s)
cnt[i] = 1;
}
for ( int i = n - 2; i >= 0; i--)
cnt[i] += cnt[i + 1];
int ans = 0;
ss = 0;
for ( int i = 0; i + 2 < n; i++) {
ss += a[i];
if (ss == s)
ans += cnt[i + 2];
}
return ans;
}
public static void Main()
{
int n = 5;
int [] a = { 1, 2, 3, 0, 3 };
Console.Write(countways(a, n));
}
}
|
Javascript
<script>
function countways(a,n)
{
let cnt = new Array(n);
let s = 0;
for (let i = 0 ; i < n ; i++)
{
s += a[i];
}
if (s % 3 != 0)
return 0;
s = Math.floor(s/3);
let ss = 0;
for (let i = n-1; i >= 0 ; i--)
{
ss += a[i];
if (ss == s)
cnt[i] = 1;
}
for (let i = n-2 ; i >= 0 ; i--)
cnt[i] += cnt[i + 1];
let ans = 0;
ss = 0;
for (let i = 0 ; i+2 < n ; i++)
{
ss += a[i];
if (ss == s)
ans += cnt[i + 2];
}
return ans;
}
let n = 5;
let a=[1, 2, 3, 0, 3];
document.write(countways(a, n));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
This approach is contributed by Abhishek Sharma. This article is contributed by Ayush Jha.
Last Updated :
13 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...