Home » Technical Interview Questions » Dynamic Programming Interview Questions » Largest area rectangular sub-matrix with equal number of 1’s and 0’s

# Largest area rectangular sub-matrix with equal number of 1’s and 0’s

Difficulty Level Medium

## Problem Statement

Given a binary matrix of size n x m. The problem is to find the largest area rectangular sub-matrix with equal number of 1’s and 0’s.

## Example ```Dimensions = 4 x 4
Matrix:
1 1 1 1
0 1 0 1
1 0 1 0
1 0 0 0
```
`12`

Explanation: If we consider the submatrix with corners (0,1), (0,3), (3,1) and (3,3). This sub-matrix makes the largest rectangular sub-matix having equal number of 0s and 1s.

```Dimesnions = 2 x 4
Matrix:
0 0 1
0 1 1
```
`6`

Explanation: Since the initial matrix had an equal number of 0s and 1s, then the initial matrix will be our answer. That’s the case here.

## Approach

### Naive Approach

The easiest thing that we can do, is considering four-pointers each for sub-matrix’s indices in all four directions. When we fixed the sub-matrix, we can count the number of 0s and 1s. But this is not an efficient approach and will surely exceed the time constraints. We can optimize the problem a bit if we change each 0 with a -1. Afterward, we find the sum of the sub-matrix using the 2D prefix sum technique. But even though using that won’t be enough.

### Efficient Approach

An efficient approach will be to first change each 0 in the matrix with a negative 1. Afterward, the problem reduces to finding the largest sub-matrix having sum 0. We have already covered this problem. This problem is solved using dynamic programming. We fix the left and right columns. Then store the sum of elements of each row from the first column to the second column in a temporary array. Then we make a map, where we store row numbers corresponding to the sum of elements while traversing this temporary array. So, if we again encounter the same sum value in our temporary array. We are sure that if we consider the elements from the row, currently being stored in a map against the sum value to this current row, will have sum 0. And when we changed 0 to -1, we had converted from largest area rectangular sub-matrix with equal number of 1’s and 0’s problem to finding the largest sub-matrix having sum 0 and now we are done with that.

## Code to find largest area rectangular sub-matrix with equal number of 1’s and 0’s

### C++ Code

```#include<bits/stdc++.h>
using namespace std;

int largestAreaRectangularSubMatrixWithEqualNumberOf1sAnd0s (vector<vector<int>> matrix, int n, int m){

// stores the prefixSum of rows
vector<vector<int>> prefixSum(n,vector<int>(m));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
prefixSum[i][j] = matrix[i][j];
}

// calculation prefix sum for each row
for(int i=0;i<n;i++){
for(int j=1;j<m;j++)
prefixSum[i][j] += prefixSum[i][j-1];
}

// store indices of submatrix with maximum sum
int startCol = 0, endCol = 0, startRow = 0, endRow = 0;
int maxSize = 0;
// use a map to first store the row for sum if it was not present earlier
// else we calculate the result regarding the particular sum
for(int firstCol=0;firstCol<m;firstCol++){
for(int secondCol=firstCol;secondCol<m;secondCol++){
int tmp[n]; // stores the sum between two columns for each row
for(int row=0;row<n;row++)
tmp[row] = prefixSum[row][secondCol] - (firstCol>0 ? prefixSum[row][firstCol-1] : 0);
int curSum = 0;
unordered_map<int,int> rowSumMap;
rowSumMap = -1;
for(int curRow=0;curRow<n;curRow++){
curSum += tmp[curRow];
if(rowSumMap.count(curSum)) {
int subMatrixSize = (secondCol - firstCol + 1)*(curRow - rowSumMap[curSum]);
if(subMatrixSize > maxSize){
maxSize = subMatrixSize;
startCol = firstCol;
endCol = secondCol;
startRow = rowSumMap[curSum] + 1;
endRow = curRow;
}
} else {
rowSumMap[curSum] = curRow;
}
}
}
}

if(maxSize == 0){
cout<<"There exists no sub-matrix with equal numbers of 0s and 1s"<<endl;
return 0;
}
cout<<"Largest Sub-matrix with equal number of 1s and 0s"<<endl;
for(int i=startRow;i<=endRow;i++){
for(int j=startCol;j<=endCol;j++){
cout<<(matrix[i][j]>0 ? 1 :  0)<<" ";
}
cout<<endl;
}
return maxSize;
}

int main(){

int t;cin>>t;
while(t--){
int n,m;cin>>n>>m;
vector<vector<int>> matrix(n,vector<int>(m));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>matrix[i][j];
matrix[i][j] = matrix[i][j] ? 1 : -1;
}
}
int ans = largestAreaRectangularSubMatrixWithEqualNumberOf1sAnd0s(matrix, n, m);
if(ans != 0)
cout<<ans<<endl;
}
}
```
```1
4 4
1 1 1 1
0 1 0 1
1 0 1 0
1 0 0 0```
```Largest Sub-matrix with equal number of 1s and 0s
1 1 1
1 0 1
0 1 0
0 0 0
12```

### Java Code

```import java.util.*;
import java.lang.*;
import java.io.*;
class Main {
static int largestAreaRectangularSubMatrixWithEqualNumberOf1sAnd0s (int[][] matrix, int n, int m){
// stores the prefixSum of rows
int[][] prefixSum = new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
prefixSum[i][j] = matrix[i][j];
}

// calculation prefix sum for each row
for(int i=0;i<n;i++){
for(int j=1;j<m;j++)
prefixSum[i][j] += prefixSum[i][j-1];
}

int startCol = 0, endCol = 0, startRow = 0, endRow = 0;
int maxSize = 0;
for(int firstCol=0;firstCol<m;firstCol++){
for(int secondCol=firstCol;secondCol<m;secondCol++){
int tmp[] = new int[n]; // stores the sum between two columns for each row
for(int row=0;row<n;row++)
tmp[row] = prefixSum[row][secondCol] - (firstCol>0 ? prefixSum[row][firstCol-1] : 0);

int curSum = 0;
HashMap<Integer, Integer> rowSumMap = new HashMap<Integer, Integer>();
rowSumMap.put(0,-1);
for(int curRow=0;curRow<n;curRow++){
curSum += tmp[curRow];
if(rowSumMap.containsKey(curSum)) {
int subMatrixSize = (secondCol - firstCol + 1)*(curRow - rowSumMap.get(curSum));
if(subMatrixSize > maxSize){
maxSize = subMatrixSize;
startCol = firstCol;
endCol = secondCol;
startRow = rowSumMap.get(curSum) + 1;
endRow = curRow;
}
} else {
rowSumMap.put(curSum,curRow);
}
}
}
}

if(maxSize == 0){
System.out.println("There exists no sub-matrix with equal number of 1s and 0s");
return 0;
}
System.out.println("Largest Rectangular Sub-matrix with equal number of 1s and 0s");
for(int i=startRow;i<=endRow;i++){
for(int j=startCol;j<=endCol;j++){
System.out.print((matrix[i][j]>0) ? "1 " : "0 ");
}
System.out.println();
}
return maxSize;
}

public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-- > 0){
int n = sc.nextInt();
int m = sc.nextInt();
int matrix[][] = new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
matrix[i][j] = sc.nextInt();
matrix[i][j] = matrix[i][j]>0 ? 1 : -1;
}
}
int ans = largestAreaRectangularSubMatrixWithEqualNumberOf1sAnd0s (matrix, n, m);
if(ans != 0)
System.out.println(ans);
}
}
}```
```1
4 4
1 1 1 1
0 1 0 1
1 0 1 0
1 0 0 0```
```Largest Rectangular Sub-matrix with equal number of 1s and 0s
1 1 1
1 0 1
0 1 0
0 0 0
12```

## Complexity Analysis

### Time Complexity: O(N^3)

We have a polynomial-time complexity of O(N^3) because there are three nested loops. One loop is used for finding the zero Sum using the prefix Sum and map technique.