Given an array containing only 0s and 1s, find the largest subarray which contains equal no of 0s and 1s. The expected time complexity is O(n).
Examples:
Input: arr[] = {1, 0, 1, 1, 1, 0, 0}
Output: 1 to 6
(Starting and Ending indexes of output subarray)
Input: arr[] = {1, 1, 1, 1}
Output: No such subarray
Input: arr[] = {0, 0, 1, 1, 0}
Output: 0 to 3 Or 1 to 4
Method 1: Brute Force.
Approach: The brute force approach in these type of questions is to generate all the possible sub-arrays. Then firstly check whether the sub-array has equal number of 0’s and 1’s or not. To make this process easy take cumulative sum of the sub-arrays taking 0’s as -1 and 1’s as it is. The point where cumulative sum = 0 will signify that the sub-array from starting till that point has equal number of 0’s and 1’s. Now as this is a valid sub-array, compare it’s size with the maximum size of such sub-array found till now.
Algorithm :
- Use a starting a pointer which signifies the starting point of the sub-array.
- Take a variable sum=0 which will take the cumulative sum of all the sub-array elements.
- Initialize it with value 1 if the value at starting point=1 else initialize it with -1.
- Now start an inner loop and start taking the cumulative sum of elements following the same logic.
- If the cumulative sum (value of sum)=0 it signifies that the sub-array has equal number of 0’s and 1’s.
- Now compare its size with the size of the largest sub-array if it is greater store the first index of such sub-array in a variable and update the value of size.
- Print the sub-array with the starting index and size returned by the above algorithm.
Pseudo Code:
Run a loop from i=0 to n-2
if(arr[i]==1)
sum=1
else
sum=-1
Run inner loop from j=i+1 to n-1
sum+=arr[j]
if(sum==0)
if(j-i+1>max_size)
start_index=i
max_size=j-i+1
Run a loop from i=start_index till max_size-1
print(arr[i])
C++
#include <bits/stdc++.h>
using namespace std;
int findSubArray( int arr[], int n)
{
int sum = 0;
int maxsize = -1, startindex;
for ( int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
for ( int j = i + 1; j < n; j++) {
(arr[j] == 0) ? (sum += -1) : (sum += 1);
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
if (maxsize == -1)
cout << "No such subarray" ;
else
cout << startindex << " to "
<< startindex + maxsize - 1;
return maxsize;
}
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof (arr) / sizeof (arr[0]);
findSubArray(arr, size);
return 0;
}
|
C
#include <stdio.h>
int findSubArray( int arr[], int n)
{
int sum = 0;
int maxsize = -1, startindex;
for ( int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
for ( int j = i + 1; j < n; j++) {
(arr[j] == 0) ? (sum += -1) : (sum += 1);
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
if (maxsize == -1)
printf ( "No such subarray" );
else
printf ( "%d to %d" , startindex, startindex + maxsize - 1);
return maxsize;
}
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof (arr) / sizeof (arr[0]);
findSubArray(arr, size);
return 0;
}
|
Java
class LargestSubArray {
int findSubArray( int arr[], int n)
{
int sum = 0 ;
int maxsize = - 1 , startindex = 0 ;
int endindex = 0 ;
for ( int i = 0 ; i < n - 1 ; i++) {
sum = (arr[i] == 0 ) ? - 1 : 1 ;
for ( int j = i + 1 ; j < n; j++) {
if (arr[j] == 0 )
sum += - 1 ;
else
sum += 1 ;
if (sum == 0 && maxsize < j - i + 1 ) {
maxsize = j - i + 1 ;
startindex = i;
}
}
}
endindex = startindex + maxsize - 1 ;
if (maxsize == - 1 )
System.out.println( "No such subarray" );
else
System.out.println(startindex + " to " + endindex);
return maxsize;
}
public static void main(String[] args)
{
LargestSubArray sub;
sub = new LargestSubArray();
int arr[] = { 1 , 0 , 0 , 1 , 0 , 1 , 1 };
int size = arr.length;
sub.findSubArray(arr, size);
}
}
|
Python3
def findSubArray(arr, n):
sum = 0
maxsize = - 1
for i in range ( 0 , n - 1 ):
sum = - 1 if (arr[i] = = 0 ) else 1
for j in range (i + 1 , n):
sum = sum + ( - 1 ) if (arr[j] = = 0 ) else sum + 1
if ( sum = = 0 and maxsize < j - i + 1 ):
maxsize = j - i + 1
startindex = i
if (maxsize = = - 1 ):
print ( "No such subarray" );
else :
print (startindex, "to" , startindex + maxsize - 1 );
return maxsize
arr = [ 1 , 0 , 0 , 1 , 0 , 1 , 1 ]
size = len (arr)
findSubArray(arr, size)
|
C#
using System;
class GFG {
static int findSubArray( int [] arr, int n)
{
int sum = 0;
int maxsize = -1, startindex = 0;
int endindex = 0;
for ( int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
for ( int j = i + 1; j < n; j++) {
if (arr[j] == 0)
sum += -1;
else
sum += 1;
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
endindex = startindex + maxsize - 1;
if (maxsize == -1)
Console.WriteLine( "No such subarray" );
else
Console.WriteLine(startindex + " to " + endindex);
return maxsize;
}
public static void Main()
{
int [] arr = { 1, 0, 0, 1, 0, 1, 1 };
int size = arr.Length;
findSubArray(arr, size);
}
}
|
PHP
<?php
function findSubArray(& $arr , $n )
{
$sum = 0;
$maxsize = -1;
for ( $i = 0; $i < $n - 1; $i ++)
{
$sum = ( $arr [ $i ] == 0) ? -1 : 1;
for ( $j = $i + 1; $j < $n ; $j ++)
{
( $arr [ $j ] == 0) ?
( $sum += -1) : ( $sum += 1);
if ( $sum == 0 && $maxsize < $j - $i + 1)
{
$maxsize = $j - $i + 1;
$startindex = $i ;
}
}
}
if ( $maxsize == -1)
echo "No such subarray" ;
else
echo $startindex . " to " .
( $startindex + $maxsize - 1);
return $maxsize ;
}
$arr = array (1, 0, 0, 1, 0, 1, 1);
$size = sizeof( $arr );
findSubArray( $arr , $size );
?>
|
Javascript
class LargestSubArray {
findSubArray(arr, n) {
let sum = 0;
let maxsize = -1;
let startindex = 0;
let endindex = 0;
for (let i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
for (let j = i + 1; j < n; j++) {
if (arr[j] == 0)
sum += -1;
else
sum += 1;
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
endindex = startindex + maxsize - 1;
if (maxsize == -1)
console.log( "No such subarray" );
else
console.log(startindex + " to " + endindex);
return maxsize;
}
main() {
const sub = new LargestSubArray();
const arr = [1, 0, 0, 1, 0, 1, 1];
const size = arr.length;
sub.findSubArray(arr, size);
}
}
const sub = new LargestSubArray();
sub.main();
|
Output:
0 to 5
Complexity Analysis:
- Time Complexity: O(n^2).
As all the possible sub-arrays are generated using a pair of nested loops.
- Auxiliary Space: O(1).
As no extra data structure is used which takes auxiliary space.
Method 2: Hashmap.
Approach: The concept of taking cumulative sum, taking 0’s as -1 will help us in optimizing the approach. While taking the cumulative sum, there are two cases when there can be a sub-array with equal number of 0’s and 1’s.
- When cumulative sum=0, which signifies that sub-array from index (0) till present index has equal number of 0’s and 1’s.
- When we encounter a cumulative sum value which we have already encountered before, which means that sub-array from the previous index+1 till the present index has equal number of 0’s and 1’s as they give a cumulative sum of 0 .
In a nutshell this problem is equivalent to finding two indexes i & j in array[] such that array[i] = array[j] and (j-i) is maximum. To store the first occurrence of each unique cumulative sum value we use a hash_map wherein if we get that value again we can find the sub-array size and compare it with the maximum size found till now.
Algorithm :
- Let input array be arr[] of size n and max_size be the size of output sub-array.
- Create a temporary array sumleft[] of size n. Store the sum of all elements from arr[0] to arr[i] in sumleft[i].
- There are two cases, the output sub-array may start from 0th index or may start from some other index. We will return the max of the values obtained by two cases.
- To find the maximum length sub-array starting from 0th index, scan the sumleft[] and find the maximum i where sumleft[i] = 0.
- Now, we need to find the subarray where subarray sum is 0 and start index is not 0. This problem is equivalent to finding two indexes i & j in sumleft[] such that sumleft[i] = sumleft[j] and j-i is maximum. To solve this, we create a hash table with size = max-min+1 where min is the minimum value in the sumleft[] and max is the maximum value in the sumleft[]. Hash the leftmost occurrences of all different values in sumleft[]. The size of hash is chosen as max-min+1 because there can be these many different possible values in sumleft[]. Initialize all values in hash as -1.
- To fill and use hash[], traverse sumleft[] from 0 to n-1. If a value is not present in hash[], then store its index in hash. If the value is present, then calculate the difference of current index of sumleft[] and previously stored value in hash[]. If this difference is more than maxsize, then update the maxsize.
- To handle corner cases (all 1s and all 0s), we initialize maxsize as -1. If the maxsize remains -1, then print there is no such subarray.
Pseudo Code:
int sum_left[n]
Run a loop from i=0 to n-1
if(arr[i]==0)
sumleft[i] = sumleft[i-1]+-1
else
sumleft[i] = sumleft[i-1]+ 1
if (sumleft[i] > max)
max = sumleft[i];
Run a loop from i=0 to n-1
if (sumleft[i] == 0)
{
maxsize = i+1;
startindex = 0;
}
// Case 2: fill hash table value. If already
then use it
if (hash[sumleft[i]-min] == -1)
hash[sumleft[i]-min] = i;
else
{
if ((i - hash[sumleft[i]-min]) > maxsize)
{
maxsize = i - hash[sumleft[i]-min];
startindex = hash[sumleft[i]-min] + 1;
}
}
return maxsize
C++
#include <bits/stdc++.h>
using namespace std;
int maxLen( int arr[], int n)
{
unordered_map< int , int > hM;
int sum = 0;
int max_len = 0;
int ending_index = -1;
for ( int i = 0; i < n; i++)
arr[i] = (arr[i] == 0) ? -1 : 1;
for ( int i = 0; i < n; i++) {
sum += arr[i];
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
if (hM.find(sum) != hM.end()) {
if (max_len < i - hM[sum]) {
max_len = i - hM[sum];
ending_index = i;
}
}
else
hM[sum] = i;
}
for ( int i = 0; i < n; i++)
arr[i] = (arr[i] == -1) ? 0 : 1;
printf ( "%d to %d\n" ,
ending_index - max_len + 1, ending_index);
return max_len;
}
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int n = sizeof (arr) / sizeof (arr[0]);
maxLen(arr, n);
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
int max( int a, int b) { return a > b ? a : b; }
int findSubArray( int arr[], int n)
{
int maxsize = -1, startindex;
int sumleft[n];
int min, max;
int i;
sumleft[0] = ((arr[0] == 0) ? -1 : 1);
min = arr[0];
max = arr[0];
for (i = 1; i < n; i++) {
sumleft[i] = sumleft[i - 1]
+ ((arr[i] == 0) ? -1 : 1);
if (sumleft[i] < min)
min = sumleft[i];
if (sumleft[i] > max)
max = sumleft[i];
}
int hash[max - min + 1];
for (i = 0; i < max - min + 1; i++)
hash[i] = -1;
for (i = 0; i < n; i++) {
if (sumleft[i] == 0) {
maxsize = i + 1;
startindex = 0;
}
if (hash[sumleft[i] - min] == -1)
hash[sumleft[i] - min] = i;
else {
if ((i - hash[sumleft[i] - min]) > maxsize) {
maxsize = i - hash[sumleft[i] - min];
startindex = hash[sumleft[i] - min] + 1;
}
}
}
if (maxsize == -1)
printf ( "No such subarray" );
else
printf ( "%d to %d" , startindex,
startindex + maxsize - 1);
return maxsize;
}
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof (arr) / sizeof (arr[0]);
findSubArray(arr, size);
return 0;
}
|
Java
import java.util.HashMap;
class LargestSubArray1 {
int maxLen( int arr[], int n)
{
HashMap<Integer, Integer> hM
= new HashMap<Integer, Integer>();
int sum = 0 ;
int max_len = 0 ;
int ending_index = - 1 ;
int start_index = 0 ;
for ( int i = 0 ; i < n; i++) {
arr[i] = (arr[i] == 0 ) ? - 1 : 1 ;
}
for ( int i = 0 ; i < n; i++) {
sum += arr[i];
if (sum == 0 ) {
max_len = i + 1 ;
ending_index = i;
}
if (hM.containsKey(sum)) {
if (max_len < i - hM.get(sum)) {
max_len = i - hM.get(sum);
ending_index = i;
}
}
else
hM.put(sum, i);
}
for ( int i = 0 ; i < n; i++) {
arr[i] = (arr[i] == - 1 ) ? 0 : 1 ;
}
int end = ending_index - max_len + 1 ;
System.out.println(end + " to " + ending_index);
return max_len;
}
public static void main(String[] args)
{
LargestSubArray1 sub = new LargestSubArray1();
int arr[] = { 1 , 0 , 0 , 1 , 0 , 1 , 1 };
int n = arr.length;
sub.maxLen(arr, n);
}
}
|
Python3
def maxLen(arr, n):
hash_map = {}
curr_sum = 0
max_len = 0
ending_index = - 1
for i in range ( 0 , n):
if (arr[i] = = 0 ):
arr[i] = - 1
else :
arr[i] = 1
for i in range ( 0 , n):
curr_sum = curr_sum + arr[i]
if (curr_sum = = 0 ):
max_len = i + 1
ending_index = i
if curr_sum in hash_map:
if max_len < i - hash_map[curr_sum]:
max_len = i - hash_map[curr_sum]
ending_index = i
else :
hash_map[curr_sum] = i
for i in range ( 0 , n):
if (arr[i] = = - 1 ):
arr[i] = 0
else :
arr[i] = 1
print (ending_index - max_len + 1 , end = " " )
print ( "to" , end = " " )
print (ending_index)
return max_len
arr = [ 1 , 0 , 0 , 1 , 0 , 1 , 1 ]
n = len (arr)
maxLen(arr, n)
|
C#
using System;
using System.Collections.Generic;
class LargestSubArray1 {
public virtual int maxLen( int [] arr, int n)
{
Dictionary< int ,
int >
hM = new Dictionary< int ,
int >();
int sum = 0;
int max_len = 0;
int ending_index = -1;
int start_index = 0;
for ( int i = 0; i < n; i++) {
arr[i] = (arr[i] == 0) ? -1 : 1;
}
for ( int i = 0; i < n; i++) {
sum += arr[i];
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
if (hM.ContainsKey(sum)) {
if (max_len < i - hM[sum]) {
max_len = i - hM[sum];
ending_index = i;
}
}
else
{
hM[sum] = i;
}
}
for ( int i = 0; i < n; i++) {
arr[i] = (arr[i] == -1) ? 0 : 1;
}
int end = ending_index - max_len + 1;
Console.WriteLine(end + " to " + ending_index);
return max_len;
}
public static void Main( string [] args)
{
LargestSubArray1 sub = new LargestSubArray1();
int [] arr = new int [] {
1,
0,
0,
1,
0,
1,
1
};
int n = arr.Length;
sub.maxLen(arr, n);
}
}
|
Javascript
function maxLen(arr, n) {
const hM = new Map();
let sum = 0;
let max_len = 0;
let ending_index = -1;
let start_index = 0;
for (let i = 0; i < n; i++) {
arr[i] = (arr[i] == 0) ? -1 : 1;
}
for (let i = 0; i < n; i++) {
sum += arr[i];
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
if (hM.has(sum)) {
if (max_len < i - hM.get(sum)) {
max_len = i - hM.get(sum);
ending_index = i;
}
} else
hM.set(sum, i);
}
for (let i = 0; i < n; i++) {
arr[i] = (arr[i] == -1) ? 0 : 1;
}
let end = ending_index - max_len + 1;
console.log(`${end} to ${ending_index}`);
return max_len;
}
let arr = [1, 0, 0, 1, 0, 1, 1];
let n = arr.length;
maxLen(arr, n);
|
Output:
0 to 5
Complexity Analysis:
- Time Complexity: O(n).
As the given array is traversed only once.
- Auxiliary Space: O(n).
As hash_map has been used which takes extra space.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!