Skip to content
Related Articles

Related Articles

Save Article
Improve Article
Save Article
Like Article

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:

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

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)




My Personal Notes arrow_drop_up
Recommended Articles
Page :