Skip to content
Related Articles

Related Articles

Divide binary array into three equal parts with same value
  • Difficulty Level : Hard
  • Last Updated : 13 Nov, 2018

Given an array A of length n such that it contains only ‘0s’ and ‘1s’. The task is to divide the array into THREE different non-empty parts such that all of these parts represent the same binary value(in decimals).
If it is possible, return any [i, j] with i+1 < j, such that:
1. A[0], A[1], …, A[i] is the first part.
2. A[i+1], A[i+2], …, A[j-1] is the second part.
3. A[j], A[j+1], …, A[n- 1] is the third part.
Note: All three parts should have equal binary value. However, If it is not possible, return [-1, -1].

Examples:

Input : A = [1, 1, 1, 1, 1, 1]
Output : [1, 4]
All three parts are,
A[0] to A[1] first part,
A[2] to A[3] second part,
A[4] to A[5] third part.

Input : A = [1, 0, 0, 1, 0, 1]
Output : [0, 4]

Approach:
Lets say total number of ones in A be S. Since every part has the same number of ones, thus all parts should have K = S / 3 ones.

If S isn’t divisible by 3 i:e S % 3 != 0, then the task is impossible.



Now we will find the position of the 1st, K-th, K+1-th, 2K-th, 2K+1-th, and 3K-th one. The positions of these ones will form 3 intervals: [i1, j1], [i2, j2], [i3, j3]. (If there are only 3 ones, then the intervals are each length 1.)

Between the intervals, there may be some number of zeros. The zeros after third interval j3 must be included in each part: say there are z of them (z = length of (S) – j3).

So the first part, [i1, j1], is now [i1, j1+z]. Similarly, the second part, [i2, j2], is now [i2, j2+z].

If all this is actually possible, then the final answer is [j1+z, j2+z+1].

Below is the implementation of above approach.

C++




// C++ implementation of the 
// above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to return required 
// interval answer.
vector<int> ThreeEqualParts(vector<int> A)
{
    int imp[] = {-1, -1};
    vector<int> IMP(imp, imp + 2);
  
    // Finding total number of ones
    int Sum = accumulate(A.begin(), 
                         A.end(), 0);
  
    if (Sum % 3)
    {
        return IMP;
    }
  
    int K = Sum / 3;
  
    // Array contains all zeros.
    if (K == 0)
    {
        return {0, (int)A.size() - 1};
    }
  
    vector<int> interval;
    int S = 0;
  
    for (int i = 0 ;i < A.size(); i++)
    {
        int x = A[i];
        if (x)
        {
            S += x;
            if (S == 1 or S == K + 1 or S == 2 * K + 1)
            {
                interval.push_back(i);
            }
            if (S == K or S == 2 * K or S == 3 * K)
            {
                interval.push_back(i);
            }
        }
    }
  
    int i1 = interval[0], j1 = interval[1],
        i2 = interval[2], j2 = interval[3],
        i3 = interval[4], j3 = interval[5];
  
    vector<int> a(A.begin() + i1, A.begin() + j1 + 1);
    vector<int> b(A.begin() + i2, A.begin() + j2 + 1);
    vector<int> c(A.begin() + i3, A.begin() + j3 + 1);
  
    // The array is in the form 
    // W [i1, j1] X [i2, j2] Y [i3, j3] Z
    // where [i1, j1] is a block of 1s, and so on.
    if (!((a == b) and (b == c)))
    {
        return {-1, -1};
    }
  
    // x, y, z: the number of zeros
    // after part 1, 2, 3
    int x = i2 - j1 - 1;
    int y = i3 - j2 - 1;
    int z = A.size() - j3 - 1;
  
    if (x < z or y < z)
    {
        return IMP;
    
  
    // appending extra zeros at end of 
    // first and second interval
    j1 += z;
    j2 += z;
    return {j1, j2 + 1}; 
}
  
// Driver Code
int main()
{
    vector<int> A = {1, 1, 1, 1, 1, 1}; 
  
    // Output required result
    vector<int> res = ThreeEqualParts(A);
  
    for(auto it :res)
        cout << it << " ";
  
    return 0;
}
  
// This code is contributed 
// by Harshit Saini 


Java




// Java implementation of the 
// above approach
import java.util.*;
  
class GFG
{
  
// Function to return required 
// interval answer.
public static int[] ThreeEqualParts(int[] A)
{
    int IMP[] = new int[]{-1, -1};
  
    // Finding total number of ones
    int Sum = Arrays.stream(A).sum();
      
    if ((Sum % 3) != 0)
    {
        return IMP;
    }
  
    int K = Sum / 3;
  
    // Array contains all zeros.
    if (K == 0)
    {
        return new int[]{0, A.length - 1};
    }
  
    ArrayList<Integer> interval = 
                   new ArrayList<Integer>();
    int S = 0;
  
    for (int i = 0 ;i < A.length; i++)
    {
        int x = A[i];
        if (x != 0)
        {
            S += x;
            if ((S == 1) || (S == K + 1) || 
                (S == 2 * K + 1))
            {
                interval.add(i);
            }
            if ((S == K) || (S == 2 * K) || 
                (S == 3 * K))
            {
                interval.add(i);
            }
        }
    }
  
    int i1 = interval.get(0), j1 = interval.get(1),
        i2 = interval.get(2), j2 = interval.get(3),
        i3 = interval.get(4), j3 = interval.get(5);
  
    int [] a = Arrays.copyOfRange(A, i1, j1 + 1);
    int [] b = Arrays.copyOfRange(A, i2, j2 + 1);
    int [] c = Arrays.copyOfRange(A, i3, j3 + 1);
  
    // The array is in the form
    // W [i1, j1] X [i2, j2] Y [i3, j3] Z
    // where [i1, j1] is a block of 1s, and so on.
    if (!(Arrays.equals(a, b) && 
          Arrays.equals(b, c)))
    {
        return new int[]{-1, -1};
    }
  
    // x, y, z: 
    // the number of zeros after part 1, 2, 3
    int x = i2 - j1 - 1;
    int y = i3 - j2 - 1;
    int z = A.length - j3 - 1;
  
    if (x < z || y < z)
    {
        return IMP;
    
  
    // appending extra zeros at end 
    // of first and second interval
    j1 += z;
    j2 += z;
    return new int[]{j1, j2 + 1}; 
}
  
// Driver Code
public static void main(String []args)
{
    int[] A = new int[]{1, 1, 1, 1, 1, 1}; 
  
    // Output required result
    int[] res = ThreeEqualParts(A);
  
    System.out.println(Arrays.toString(res));
}
}
  
// This code is contributed 
// by Harshit Saini 


Python3




# Python implementation of the above approach
  
# Function to return required interval answer.
def ThreeEqualParts(A):
    IMP = [-1, -1]
  
    # Finding total number of ones
    Sum = sum(A)
  
    if Sum % 3:
        return IMP
  
    K = Sum / 3
  
    # Array contains all zeros.
    if K == 0:
        return [0, len(A) - 1]
  
    interval = []
    S = 0
  
    for i, x in enumerate(A):
        if x:
            S += x
            if S in {1, K + 1, 2 * K + 1}:
                interval.append(i)
            if S in {K, 2 * K, 3 * K}:
                interval.append(i)
  
    i1, j1, i2, j2, i3, j3 = interval
  
    # The array is in the form W [i1, j1] X [i2, j2] Y [i3, j3] Z
    # where [i1, j1] is a block of 1s, and so on.
    if not(A[i1:j1 + 1] == A[i2:j2 + 1] == A[i3:j3 + 1]):
        return [-1, -1]
  
    # x, y, z: the number of zeros after part 1, 2, 3
    x = i2 - j1 - 1
    y = i3 - j2 - 1
    z = len(A) - j3 - 1
  
    if x < z or y < z:
        return IMP
  
    # appending extra zeros at end of first and second interval
    j1 += z
    j2 += z
    return [j1, j2 + 1]
  
  
# Driver Program
A = [1, 1, 1, 1, 1, 1]
  
# Output required result
print(ThreeEqualParts(A))
  
# This code is written by
# Sanjit_Prasad


C#




// C# implementation of the 
// above approach
using System;
using System.Linq;
using System.Collections.Generic;
  
class GFG
{
  
// Function to return required
// interval answer.
static int[] ThreeEqualParts(int[] A)
{
  
    int []IMP = new int[]{-1, -1};
  
    // Finding total number of ones
    int Sum = A.Sum();
      
    if ((Sum % 3) != 0)
    {
        return IMP;
    }
  
  
    int K = Sum / 3;
  
    // Array contains all zeros.
    if (K == 0)
    {
        return new int[]{0, A.Length - 1};
    }
  
    List<int> interval = new List<int>();
  
    int S = 0;
  
    for (int i = 0 ;i < A.Length; i++)
    {
        int x = A[i];
        if (x != 0)
        {
            S += x;
            if ((S == 1) || (S == K + 1) || 
                (S == 2 * K + 1))
            {
                interval.Add(i);
            }
            if ((S == K) || (S == 2 * K) || 
                (S == 3 * K))
            {
                interval.Add(i);
            }
        }
    }
  
    int i1 = interval[0], j1 = interval[1],
        i2 = interval[2], j2 = interval[3],
        i3 = interval[4], j3 = interval[5];
  
    var a = A.Skip(i1).Take(j1 - i1 + 1).ToArray();
    var b = A.Skip(i2).Take(j2 - i2 + 1).ToArray();
    var c = A.Skip(i3).Take(j3 - i3 + 1).ToArray();
  
    // The array is in the form 
    // W [i1, j1] X [i2, j2] Y [i3, j3] Z
    // where [i1, j1] is a block of 1s,
    // and so on.
    if (!(Enumerable.SequenceEqual(a,b) && 
          Enumerable.SequenceEqual(b,c)))
    {
        return new int[]{-1, -1};
    }
  
    // x, y, z: the number of zeros
    // after part 1, 2, 3
    int X = i2 - j1 - 1;
    int y = i3 - j2 - 1;
    int z = A.Length - j3 - 1;
  
    if (X < z || y < z)
    {
        return IMP;
    
  
    // appending extra zeros at end 
    // of first and second interval
    j1 += z;
    j2 += z;
    return new int[]{j1, j2 + 1}; 
}
  
// Driver Code
public static void Main()
{
    int[] A = new int[]{1, 1, 1, 1, 1, 1}; 
  
    // Output required result
    int[] res = ThreeEqualParts(A);
  
    Console.WriteLine(string.Join(" ", res));
}
}
  
// This code is contributed 
// by Harshit Saini 


PHP




<?php
// PHP implementation of the
// above approach
  
// Function to return required 
// interval answer.
function ThreeEqualParts($A)
{
  
    $IMP = array(-1, -1);
  
    // Finding total number of ones
    $Sum = array_sum($A);
  
    if ($Sum % 3)
    {
        return $IMP;
    }
    $K = $Sum / 3;
  
    // Array contains all zeros.
    if ($K == 0)
    {
        return array(0, count(A, 
                     COUNT_NORMAL) - 1);
    }
  
    $interval = array();
    $S = 0;
  
    for ($i = 0; 
         $i < count($A, COUNT_NORMAL); $i++)
    {
        $x = $A[$i];
        if ($x)
        {
            $S += $x;
            if ($S == 1 or $S == $K + 1 or
                $S == 2 * $K + 1)
            {
                array_push($interval,$i);
            }
            if ($S == $K or $S == 2 * $K or
                $S == 3 * $K)
            {
                array_push($interval, $i);
            }
        }
    }
  
    $i1 = $interval[0]; $j1 = $interval[1];
    $i2 = $interval[2]; $j2 = $interval[3];
    $i3 = $interval[4]; $j3 = $interval[5];
  
    $a = array_slice($A, $i1, $j1 - $i1 + 1);
    $b = array_slice($A, $i1, $j2 - $i2 + 1);
    $c = array_slice($A, $i1, $j3 - $i3 + 1);
  
    // The array is in the form  
    // W [i1, j1] X [i2, j2] Y [i3, j3] Z
    // where [i1, j1] is a block of 1s,
    // and so on.
    if (!($a == $b and $b == $c))
    {
        return array(-1, -1);
    }
  
    // x, y, z: the number of zeros
    // after part 1, 2, 3
    $x = $i2 - $j1 - 1;
    $y = $i3 - $j2 - 1;
    $z = count($A) - $j3 - 1;
  
    if ($x < $z or $y < $z)
    {
        return $IMP;
    
  
    // appending extra zeros at end 
    // of first and second interval
    $j1 += $z;
    $j2 += $z;
    return array($j1, $j2 + 1); 
}
  
// Driver Code
$A = array(1, 1, 1, 1, 1, 1); 
  
// Output required result
$res = ThreeEqualParts($A);
  
foreach ($res as $key => $value
{
    echo $value." ";
}
  
// This code is contributed 
// by Harshit Saini 
?>



Output:

1 4 

Time Complexity: O(N), where N is the length of S.
Space Complexity: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :