Divide binary array into three equal parts with same value

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?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 
?>

chevron_right



Output:

1 4 

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



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Harshit Saini



Article Tags :
Practice Tags :


2


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.