Given a 2D binary matrix mat[][] consisting only of 0s and 1s, find the area of the largest rectangle sub-matrix that contains only 1s.
Examples:
Input: mat[][] = [[0, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 0, 0]] Output: 8 Explanation: The largest rectangle of 1's highlighted in green, matching the area of 2 * 4 = 8.
Input: mat[][] = [[0, 1, 1], [1, 1, 1], [0, 1, 1]] Output: 6 Explanation: The largest rectangle of 1's highlighted in green, matching the area of 3 * 2 = 6.
[Naive Approach] Check All Possible Rectangles - O(n ^ 2 * m ^2 * n * m) Time and O(1) Space
The idea is to generate every possible rectangle in the matrix by choosing its top-left and bottom-right corners. For each rectangle, check whether all its cells contain 1. If yes, compute its area and update the maximum area. Finally, return the largest valid rectangle found.
Working of Approach:
Generate every possible rectangle using four nested loops.
For each rectangle, traverse all its cells.
If every cell is 1, compute its area.
Update the maximum rectangle area.
Return the maximum area after checking all rectangles.
C++
#include<iostream>#include<vector>usingnamespacestd;// Function to find the maximum rectangle area.intmaxArea(vector<vector<int>>&mat){intn=mat.size();intm=mat[0].size();intres=0;// Choose the top-left corner.for(inttop=0;top<n;top++){for(intleft=0;left<m;left++){// Choose the bottom-right corner.for(intbottom=top;bottom<n;bottom++){for(intright=left;right<m;right++){boolvalid=true;// Check whether all cells inside// the rectangle are 1.for(inti=top;i<=bottom&&valid;i++){for(intj=left;j<=right;j++){if(mat[i][j]==0){valid=false;break;}}}// Update the maximum area if the rectangle// contains only 1's.if(valid){intarea=(bottom-top+1)*(right-left+1);res=max(res,area);}}}}}returnres;}intmain(){vector<vector<int>>mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};cout<<maxArea(mat);return0;}
Java
importjava.util.*;classGFG{// Function to find the maximum rectangle area.publicintmaxArea(int[][]mat){intn=mat.length;intm=mat[0].length;intres=0;// Choose the top-left corner.for(inttop=0;top<n;top++){for(intleft=0;left<m;left++){// Choose the bottom-right corner.for(intbottom=top;bottom<n;bottom++){for(intright=left;right<m;right++){booleanvalid=true;// Check whether all cells inside// the rectangle are 1.for(inti=top;i<=bottom&&valid;i++){for(intj=left;j<=right;j++){if(mat[i][j]==0){valid=false;break;}}}// Update the maximum area if the// rectangle contains only 1's.if(valid){intarea=(bottom-top+1)*(right-left+1);res=Math.max(res,area);}}}}}returnres;}publicstaticvoidmain(String[]args){int[][]mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};GFGobj=newGFG();System.out.println(obj.maxArea(mat));}}
Python
defmaxArea(mat):n=len(mat)m=len(mat[0])res=0# Choose the top-left corner.fortopinrange(n):forleftinrange(m):# Choose the bottom-right corner.forbottominrange(top,n):forrightinrange(left,m):valid=True# Check whether all cells inside# the rectangle are 1.foriinrange(top,bottom+1):forjinrange(left,right+1):ifmat[i][j]==0:valid=Falsebreakifnotvalid:break# Update the maximum area if the rectangle# contains only 1's.ifvalid:area=(bottom-top+1)*(right-left+1)res=max(res,area)returnresif__name__=="__main__":mat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]print(maxArea(mat))
C#
usingSystem;publicclassGFG{// Function to find the maximum rectangle area.publicintmaxArea(int[][]mat){intn=mat.Length;intm=mat[0].Length;intres=0;// Choose the top-left corner.for(inttop=0;top<n;top++){for(intleft=0;left<m;left++){// Choose the bottom-right corner.for(intbottom=top;bottom<n;bottom++){for(intright=left;right<m;right++){boolvalid=true;// Check whether all cells inside// the rectangle are 1.for(inti=top;i<=bottom&&valid;i++){for(intj=left;j<=right;j++){if(mat[i][j]==0){valid=false;break;}}}// Update the maximum area if the// rectangle contains only 1's.if(valid){intarea=(bottom-top+1)*(right-left+1);res=Math.Max(res,area);}}}}}returnres;}publicstaticvoidMain(){int[][]mat={newint[]{0,1,1,0},newint[]{1,1,1,1},newint[]{1,1,1,1},newint[]{1,1,0,0}};GFGobj=newGFG();Console.WriteLine(obj.maxArea(mat));}}
JavaScript
functionmaxArea(mat){constn=mat.length;constm=mat[0].length;letres=0;// Choose the top-left corner.for(lettop=0;top<n;top++){for(letleft=0;left<m;left++){// Choose the bottom-right corner.for(letbottom=top;bottom<n;bottom++){for(letright=left;right<m;right++){letvalid=true;// Check whether all cells inside// the rectangle are 1.for(leti=top;i<=bottom&&valid;i++){for(letj=left;j<=right;j++){if(mat[i][j]===0){valid=false;break;}}}// Update the maximum area if the// rectangle contains only 1's.if(valid){constarea=(bottom-top+1)*(right-left+1);res=Math.max(res,area);}}}}}returnres;}// Driver Codeconstmat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]];console.log(maxArea(mat));
Output
8
[Better Approach] Using Dynamic Programming - O((n ^ 2) * m) Time and O(n * m) Space
The idea is to store, for each cell (i, j), the width of consecutive 1’s ending at that position in a 2D array. Then, for every cell (i, j) with value 1, iterate upwards row by row. While moving upward, keep track of the minimum width of 1’s seen so far in that column. This ensures the rectangle formed remains valid. At each step, the rectangle area is computed as: (area = minWidth * height).
Working of Approach:
Build a DP table memo[][], where memo[i][j] stores the width of consecutive 1s ending at cell (i, j).
Traverse each cell containing 1 and treat it as the bottom-right corner of a rectangle.
Move upwards row by row while maintaining the minimum width encountered so far.
Compute the rectangle area for every possible height and update the maximum area.
Return the maximum area after processing all cells.
C++
#include<algorithm>#include<iostream>#include<vector>usingnamespacestd;intmaxArea(vector<vector<int>>&mat){intn=mat.size(),m=mat[0].size();// memo[i][j] stores the width of consecutive 1's// ending at position (i, j).vector<vector<int>>memo(n,vector<int>(m,0));intres=0;for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==0)continue;// Compute width of 1's at (i, j).memo[i][j]=(j==0)?1:memo[i][j-1]+1;intwidth=memo[i][j];// Traverse upwards row by row,// update minimum width and calculate area.for(intk=i;k>=0;k--){width=min(width,memo[k][j]);intarea=width*(i-k+1);res=max(res,area);}}}returnres;}intmain(){vector<vector<int>>mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};cout<<maxArea(mat)<<endl;return0;}
Java
importjava.util.*;classGFG{publicintmaxArea(int[][]mat){intn=mat.length,m=mat[0].length;// memo[i][j] stores the width of consecutive 1's// ending at position (i, j).int[][]memo=newint[n][m];intres=0;for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==0)continue;// Compute width of 1's at (i, j).memo[i][j]=(j==0)?1:memo[i][j-1]+1;intwidth=memo[i][j];// Traverse upwards row by row,// update minimum width and calculate area.for(intk=i;k>=0;k--){width=Math.min(width,memo[k][j]);intarea=width*(i-k+1);res=Math.max(res,area);}}}returnres;}publicstaticvoidmain(String[]args){int[][]mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};GFGobj=newGFG();System.out.println(obj.maxArea(mat));}}
Python
defmaxArea(mat):n=len(mat)m=len(mat[0])# memo[i][j] stores the width of consecutive 1's# ending at position (i, j).memo=[[0]*mfor_inrange(n)]res=0foriinrange(n):forjinrange(m):ifmat[i][j]==0:continue# Compute width of 1's at (i, j).memo[i][j]=1ifj==0elsememo[i][j-1]+1width=memo[i][j]# Traverse upwards row by row,# update minimum width and calculate area.forkinrange(i,-1,-1):width=min(width,memo[k][j])area=width*(i-k+1)res=max(res,area)returnresif__name__=='__main__':mat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]print(maxArea(mat))
C#
usingSystem;publicclassGFG{publicintmaxArea(int[][]mat){intn=mat.Length,m=mat[0].Length;// memo[i][j] stores the width of consecutive 1's// ending at position (i, j).int[][]memo=newint[n][];for(inti=0;i<n;i++)memo[i]=newint[m];intres=0;for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==0)continue;// Compute width of 1's at (i, j).memo[i][j]=(j==0)?1:memo[i][j-1]+1;intwidth=memo[i][j];// Traverse upwards row by row,// update minimum width and calculate area.for(intk=i;k>=0;k--){width=Math.Min(width,memo[k][j]);intarea=width*(i-k+1);res=Math.Max(res,area);}}}returnres;}publicstaticvoidMain(){int[][]mat={newint[]{0,1,1,0},newint[]{1,1,1,1},newint[]{1,1,1,1},newint[]{1,1,0,0}};GFGobj=newGFG();Console.WriteLine(obj.maxArea(mat));}}
JavaScript
functionmaxArea(mat){letn=mat.length,m=mat[0].length;// memo[i][j] stores the width of consecutive 1's// ending at position (i, j).letmemo=Array.from({length:n},()=>Array(m).fill(0));letres=0;for(leti=0;i<n;i++){for(letj=0;j<m;j++){if(mat[i][j]===0)continue;// Compute width of 1's at (i, j).memo[i][j]=(j===0)?1:memo[i][j-1]+1;letwidth=memo[i][j];// Traverse upwards row by row,// update minimum width and calculate area.for(letk=i;k>=0;k--){width=Math.min(width,memo[k][j]);letarea=width*(i-k+1);res=Math.max(res,area);}}}returnres;}// Driver Codeletmat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]];console.log(maxArea(mat));
Output
8
[Expected Approach] Using Largest Rectangular Area in a Histogram - O(n * m) Time and O(m) Space
The idea is to treat each row as the base of a histogram by maintaining the heights of consecutive 1s in every column. Then, the known stack-based Largest Rectangle in Histogram algorithm gives the maximum area for that row. Repeat this for all rows and return the maximum area obtained.
Working of Approach:
Maintain a histogram array where each element stores the number of consecutive 1s in that column up to the current row.
Traverse the matrix row by row and update the histogram by increasing the height for 1 and resetting it to 0 for 0.
For every updated histogram, use a monotonic increasing stack to find the largest rectangle in linear time.
The stack helps determine the maximum width for every bar by finding its previous and next smaller elements.
Update the maximum rectangle area for each row and return the overall maximum.
Let us understand with an example: Input: mat[][] = [[0, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 0, 0]]
Row 0: Histogram = [0, 1, 1, 0], largest rectangle area = 2.
Row 1: Histogram = [1, 2, 2, 1], largest rectangle area = 4.
Row 2: Histogram = [2, 3, 3, 2], largest rectangle area = 8.
Row 3: Histogram = [3, 4, 0, 0], largest rectangle area = 6.
Therefore, the maximum rectangle consisting of only 1s has area 8.
C++
#include<algorithm>#include<iostream>#include<stack>#include<vector>usingnamespacestd;// Function to find the maximum area of// rectangle in a histogram.intgetMaxArea(vector<int>&arr){intn=arr.size();stack<int>s;intres=0;inttp,curr;for(inti=0;i<n;i++){while(!s.empty()&&arr[s.top()]>=arr[i]){// The popped item is to be considered as the// smallest element of the histogramtp=s.top();s.pop();// For the popped item previous smaller element is// just below it in the stack (or current stack top)// and next smaller element is iintwidth=s.empty()?i:i-s.top()-1;res=max(res,arr[tp]*width);}s.push(i);}// For the remaining items in the stack, next smaller does// not exist. Previous smaller is the item just below in// stack.while(!s.empty()){tp=s.top();s.pop();curr=arr[tp]*(s.empty()?n:n-s.top()-1);res=max(res,curr);}returnres;}// Function to find the maximum area of rectangle// in a 2D matrix.intmaxArea(vector<vector<int>>&mat){intn=mat.size(),m=mat[0].size();// Array to store matrix// as a histogram.vector<int>arr(m,0);intres=0;// Traverse row by row.for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==1){arr[j]++;}else{arr[j]=0;}}res=max(res,getMaxArea(arr));}returnres;}intmain(){vector<vector<int>>mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};cout<<maxArea(mat)<<endl;return0;}
Java
importjava.util.*;classGFG{// Function to find the maximum area of// rectangle in a histogram.publicintgetMaxArea(int[]arr){intn=arr.length;Stack<Integer>s=newStack<>();intres=0;inttp,curr;for(inti=0;i<n;i++){while(!s.isEmpty()&&arr[s.peek()]>=arr[i]){// The popped item is to be considered as// the smallest element of the histogramtp=s.pop();// For the popped item previous smaller// element is just below it in the stack (or// current stack top) and next smaller// element is iintwidth=s.isEmpty()?i:i-s.peek()-1;res=Math.max(res,arr[tp]*width);}s.push(i);}// For the remaining items in the stack, next// smaller does not exist. Previous smaller is the// item just below in stack.while(!s.isEmpty()){tp=s.pop();curr=arr[tp]*(s.isEmpty()?n:n-s.peek()-1);res=Math.max(res,curr);}returnres;}// Function to find the maximum area of rectangle// in a 2D matrix.publicintmaxArea(int[][]mat){intn=mat.length,m=mat[0].length;// Array to store matrix// as a histogram.int[]arr=newint[m];intres=0;// Traverse row by row.for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==1){arr[j]++;}else{arr[j]=0;}}res=Math.max(res,getMaxArea(arr));}returnres;}publicstaticvoidmain(String[]args){int[][]mat={{0,1,1,0},{1,1,1,1},{1,1,1,1},{1,1,0,0}};GFGobj=newGFG();System.out.println(obj.maxArea(mat));}}
Python
fromtypingimportList# Function to find the maximum area of# rectangle in a histogram.defgetMaxArea(arr:List[int])->int:n=len(arr)s=[]res=0tp,curr=0,0foriinrange(n):whilesandarr[s[-1]]>=arr[i]:# The popped item is to be considered as the# smallest element of the histogramtp=s.pop()# For the popped item previous smaller element is# just below it in the stack (or current stack top)# and next smaller element is iwidth=iifnotselsei-s[-1]-1res=max(res,arr[tp]*width)s.append(i)# For the remaining items in the stack, next smaller does# not exist. Previous smaller is the item just below in# stack.whiles:tp=s.pop()curr=arr[tp]*(nifnotselsen-s[-1]-1)res=max(res,curr)returnres# Function to find the maximum area of rectangle# in a 2D matrix.defmaxArea(mat:List[List[int]])->int:n=len(mat)m=len(mat[0])# Array to store matrix# as a histogram.arr=[0]*mres=0# Traverse row by row.foriinrange(n):forjinrange(m):ifmat[i][j]==1:arr[j]+=1else:arr[j]=0res=max(res,getMaxArea(arr))returnresif__name__=="__main__":mat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]print(maxArea(mat))
C#
usingSystem;usingSystem.Collections.Generic;publicclassGFG{// Function to find the maximum area of// rectangle in a histogram.staticintgetMaxArea(int[]arr){intn=arr.Length;Stack<int>s=newStack<int>();intres=0;inttp,curr;for(inti=0;i<n;i++){while(s.Count>0&&arr[s.Peek()]>=arr[i]){// The popped item is to be considered as// the smallest element of the histogramtp=s.Pop();// For the popped item previous smaller// element is just below it in the stack (or// current stack top) and next smaller// element is iintwidth=s.Count==0?i:i-s.Peek()-1;res=Math.Max(res,arr[tp]*width);}s.Push(i);}// For the remaining items in the stack, next// smaller does not exist. Previous smaller is the// item just below in stack.while(s.Count>0){tp=s.Pop();curr=arr[tp]*(s.Count==0?n:n-s.Peek()-1);res=Math.Max(res,curr);}returnres;}// Function to find the maximum area of rectangle// in a 2D matrix.publicintmaxArea(int[][]mat){intn=mat.Length,m=mat[0].Length;// Array to store matrix// as a histogram.int[]arr=newint[m];intres=0;// Traverse row by row.for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(mat[i][j]==1){arr[j]++;}else{arr[j]=0;}}res=Math.Max(res,getMaxArea(arr));}returnres;}publicstaticvoidMain(){int[][]mat={newint[]{0,1,1,0},newint[]{1,1,1,1},newint[]{1,1,1,1},newint[]{1,1,0,0}};GFGobj=newGFG();Console.WriteLine(obj.maxArea(mat));}}
JavaScript
functiongetMaxArea(arr){letn=arr.length;lets=[];letres=0;lettp,curr;for(leti=0;i<n;i++){while(s.length>0&&arr[s[s.length-1]]>=arr[i]){// The popped item is to be considered as the// smallest element of the histogramtp=s.pop();// For the popped item previous smaller element// is just below it in the stack (or current// stack top) and next smaller element is iletwidth=s.length===0?i:i-s[s.length-1]-1;res=Math.max(res,arr[tp]*width);}s.push(i);}// For the remaining items in the stack, next smaller// does not exist. Previous smaller is the item just// below in stack.while(s.length>0){tp=s.pop();curr=arr[tp]*(s.length===0?n:n-s[s.length-1]-1);res=Math.max(res,curr);}returnres;}functionmaxArea(mat){letn=mat.length,m=mat[0].length;// Array to store matrix// as a histogram.letarr=newArray(m).fill(0);letres=0;// Traverse row by row.for(leti=0;i<n;i++){for(letj=0;j<m;j++){if(mat[i][j]===1){arr[j]++;}else{arr[j]=0;}}res=Math.max(res,getMaxArea(arr));}returnres;}// Driver Codeletmat=[[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]];console.log(maxArea(mat));