Divide binary array into three equal parts with same value - GeeksforGeeks

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++
Java
Python3
C#
PHP
// 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 Codeint 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 implementation of the // above approachimport 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 Codepublic 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 
# 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 ProgramA = [1, 1, 1, 1, 1, 1]  # Output required resultprint(ThreeEqualParts(A))  # This code is written by# Sanjit_Prasad
// C# implementation of the // above approachusing 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 Codepublic 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 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 ?>
1 4 
Time Complexity: O(N), where N is the length of S.Space Complexity: O(N)
Harshit Saini
binary-string
Arrays
Arrays
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum and minimum of an array using minimum number of comparisons
Stack Data Structure (Introduction and Program)
Top 50 Array Coding Problems for Interviews
Multidimensional Arrays in Java
Introduction to Arrays
Linear Search
Python | Using 2D arrays/lists the right way
Linked List vs Array
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Queue | Set 1 (Introduction and Array Implementation)