Given an array arr[] representing a histogram, where each element denotes the height of a bar and every bar has a uniform width of 1 unit, find the largest rectangular area that can be formed within the histogram. The rectangle must be formed using contiguous bars.
Example:
Input: arr[] = [60, 20, 50, 40, 10, 50, 60] Output: 100 Explanation: We get the maximum area by picking bars highlighted above in green (50, and 60). The area is computed (smallest height) * (no. of the picked bars) = 50 * 2 = 100.
Input: arr[] = [3, 5, 1, 7, 5, 9] Output: 15 Explanation: We get the maximum are by picking bars 7, 5 and 9. The area is computed (smallest height) * (no. of the picked bars) = 5 * 3 = 15.
[Naive Approach] By Finding Max Area of Rectangles all Heights - O(n2) Time and O(1) Space
The idea is to fix each bar as the height of the rectangle and expand towards the left and right while the bars are at least as tall as the current bar. For every valid step, we keep adding the current bar’s height to the area. By doing this for all bars and keeping track of the maximum value.
C++
#include<iostream>#include<vector>usingnamespacestd;intgetMaxArea(vector<int>&arr){intres=0,n=arr.size();// Consider every bar one by onefor(inti=0;i<n;i++){intcurr=arr[i];// Traverse left while we have a greater height barfor(intj=i-1;j>=0&&arr[j]>=arr[i];j--)curr+=arr[i];// Traverse right while we have a greater height bar for(intj=i+1;j<n&&arr[j]>=arr[i];j++)curr+=arr[i];res=max(res,curr);}returnres;}intmain(){vector<int>arr={60,20,50,40,10,50,60};cout<<getMaxArea(arr);return0;}
C
#include<stdio.h>intgetMaxArea(intarr[],intn){intres=0;// Consider every bar one by onefor(inti=0;i<n;i++){intcurr=arr[i];// Traverse left while we have a greater height barfor(intj=i-1;j>=0&&arr[j]>=arr[i];j--){curr+=arr[i];}// Traverse right while we have a greater height barfor(intj=i+1;j<n&&arr[j]>=arr[i];j++){curr+=arr[i];}if(curr>res){res=curr;}}returnres;}intmain(){intarr[]={60,20,50,40,10,50,60};intn=sizeof(arr)/sizeof(arr[0]);printf("%d\n",getMaxArea(arr,n));return0;}
Java
classGfG{staticintgetMaxArea(int[]arr){intres=0,n=arr.length;for(inti=0;i<n;i++){intcurr=arr[i];// Traverse left while we have a greater height barfor(intj=i-1;j>=0&&arr[j]>=arr[i];j--)curr+=arr[i];// Traverse right while we have a greater height barfor(intj=i+1;j<n&&arr[j]>=arr[i];j++)curr+=arr[i];res=Math.max(res,curr);}returnres;}publicstaticvoidmain(String[]args){int[]arr={60,20,50,40,10,50,60};System.out.println(getMaxArea(arr));}}
Python
defgetMaxArea(arr):res=0n=len(arr)foriinrange(n):curr=arr[i]# Traverse left while we have a greater height barj=i-1whilej>=0andarr[j]>=arr[i]:curr+=arr[i]j-=1# Traverse right while we have a greater height barj=i+1whilej<nandarr[j]>=arr[i]:curr+=arr[i]j+=1res=max(res,curr)returnresif__name__=="__main__":arr=[60,20,50,40,10,50,60]print(getMaxArea(arr))
C#
usingSystem;classGfG{staticintgetMaxArea(int[]arr){intn=arr.Length;intres=0;// Consider every bar one by onefor(inti=0;i<n;i++){intcurr=arr[i];// Traverse left while we have a greater height barintj=i-1;while(j>=0&&arr[j]>=arr[i]){curr+=arr[i];j--;}// Traverse right while we have a greater height barj=i+1;while(j<n&&arr[j]>=arr[i]){curr+=arr[i];j++;}res=Math.Max(res,curr);}returnres;}staticvoidMain(string[]args){int[]arr={60,20,50,40,10,50,60};Console.WriteLine(getMaxArea(arr));}}
JavaScript
functiongetMaxArea(arr){letn=arr.length;letres=0;// Consider every bar one by onefor(leti=0;i<n;i++){letcurr=arr[i];// Traverse left while we have a greater height barletj=i-1;while(j>=0&&arr[j]>=arr[i]){curr+=arr[i];j--;}// Traverse right while we have a greater height barj=i+1;while(j<n&&arr[j]>=arr[i]){curr+=arr[i];j++;}res=Math.max(res,curr);}returnres;}// Driver codeletarr=[60,20,50,40,10,50,60];console.log(getMaxArea(arr));
Output
100
[Expected Approach] Using Two Stacks - O(n) Time and O(n) Space
The idea is that Instead of recalculating the left and right boundary for every bar, we can precompute them once.
The Next Smaller Element (NSE) tells us the nearest bar on the right that is smaller than the current bar.
With these two values, we instantly know the maximum width a bar can extend while maintaining itself as the limiting height. Finally, multiplying this width with the current bar’s height gives the largest rectangle for that bar, and taking the maximum across all bars gives the answer.
C++
#include<iostream>#include<stack>#include<vector>usingnamespacestd;// Function to find next smaller for every elementvector<int>nextSmaller(vector<int>&arr){intn=arr.size();vector<int>nextS(n,n);stack<int>st;for(inti=0;i<n;++i){while(!st.empty()&&arr[i]<arr[st.top()]){// Setting the index of the next smaller element// for the top of the stacknextS[st.top()]=i;st.pop();}st.push(i);}returnnextS;}// Function to find previous smaller for every elementvector<int>prevSmaller(vector<int>&arr){intn=arr.size();vector<int>prevS(n,-1);stack<int>st;for(inti=0;i<n;++i){while(!st.empty()&&arr[i]<arr[st.top()]){// Setting the index of the previous smaller element// for the top of the stackst.pop();}if(!st.empty()){prevS[i]=st.top();}st.push(i);}returnprevS;}// Function to calculate the maximum rectangular// area in the HistogramintgetMaxArea(vector<int>&arr){vector<int>prevS=prevSmaller(arr);vector<int>nextS=nextSmaller(arr);intmaxArea=0;// Calculate the area for each Histogram barfor(inti=0;i<arr.size();++i){intwidth=nextS[i]-prevS[i]-1;intarea=arr[i]*width;maxArea=max(maxArea,area);}returnmaxArea;}intmain(){vector<int>arr={60,20,50,40,10,50,60};cout<<getMaxArea(arr)<<endl;return0;}
C
#include<stdio.h>#include<stdlib.h>// Stack structurestructStack{inttop;intcapacity;int*items;};// Function to create an empty stack with dynamic memory allocationstructStack*createStack(intcapacity){structStack*stack=(structStack*)malloc(sizeof(structStack));stack->capacity=capacity;stack->top=-1;stack->items=(int*)malloc(stack->capacity*sizeof(int));returnstack;}// Function to check if the stack is emptyintisEmpty(structStack*stack){returnstack->top==-1;}// Function to push an element onto the stackvoidpush(structStack*stack,intvalue){if(stack->top==stack->capacity-1){printf("Stack overflow\n");return;}stack->items[++(stack->top)]=value;}// Function to pop an element from the stackintpop(structStack*stack){if(isEmpty(stack)){printf("Stack underflow\n");return-1;}returnstack->items[(stack->top)--];}// Function to get the top element of the stackintpeek(structStack*stack){if(!isEmpty(stack)){returnstack->items[stack->top];}return-1;}// Function to find the next smaller element for every elementvoidnextSmaller(intarr[],intn,intnextS[]){structStack*stack=createStack(n);for(inti=0;i<n;i++){nextS[i]=n;}for(inti=0;i<n;i++){while(!isEmpty(stack)&&arr[i]<arr[peek(stack)]){nextS[peek(stack)]=i;pop(stack);}push(stack,i);}}// Function to find the previous smaller element for every elementvoidprevSmaller(intarr[],intn,intprevS[]){structStack*stack=createStack(n);for(inti=0;i<n;i++){prevS[i]=-1;}for(inti=0;i<n;i++){while(!isEmpty(stack)&&arr[i]<arr[peek(stack)]){pop(stack);}if(!isEmpty(stack)){prevS[i]=peek(stack);}push(stack,i);}}// Function to calculate the maximum rectangular// area in the HistogramintgetMaxArea(intarr[],intn){int*prevS=(int*)malloc(n*sizeof(int));int*nextS=(int*)malloc(n*sizeof(int));intmaxArea=0;// Find previous and next smaller elementsprevSmaller(arr,n,prevS);nextSmaller(arr,n,nextS);// Calculate the area for each arrogram barfor(inti=0;i<n;i++){intwidth=nextS[i]-prevS[i]-1;intarea=arr[i]*width;if(area>maxArea){maxArea=area;}}returnmaxArea;}// Driver codeintmain(){intarr[]={60,20,50,40,10,50,60};intn=sizeof(arr)/sizeof(arr[0]);printf("%d\n",getMaxArea(arr,n));return0;}
Java
importjava.util.Stack;classGfG{// Function to find next smaller for every elementstaticint[]nextSmaller(int[]arr){intn=arr.length;int[]nextS=newint[n];for(inti=0;i<n;i++){nextS[i]=n;}Stack<Integer>st=newStack<>();for(inti=0;i<n;i++){while(!st.isEmpty()&&arr[i]<arr[st.peek()]){// Setting the index of the next smaller element// for the top of the stacknextS[st.pop()]=i;}st.push(i);}returnnextS;}// Function to find previous smaller for every elementstaticint[]prevSmaller(int[]arr){intn=arr.length;int[]prevS=newint[n];for(inti=0;i<n;i++){prevS[i]=-1;}Stack<Integer>st=newStack<>();for(inti=0;i<n;i++){while(!st.isEmpty()&&arr[i]<arr[st.peek()]){st.pop();}if(!st.isEmpty()){prevS[i]=st.peek();}st.push(i);}returnprevS;}// Function to calculate the maximum rectangular// area in the histogramstaticintgetMaxArea(int[]arr){int[]prevS=prevSmaller(arr);int[]nextS=nextSmaller(arr);intmaxArea=0;// Calculate the area for each arrogram barfor(inti=0;i<arr.length;i++){intwidth=nextS[i]-prevS[i]-1;intarea=arr[i]*width;maxArea=Math.max(maxArea,area);}returnmaxArea;}publicstaticvoidmain(String[]args){int[]arr={60,20,50,40,10,50,60};System.out.println(getMaxArea(arr));}}
Python
# Function to find next smaller for every elementdefnextSmaller(arr):n=len(arr)nextS=[n]*nst=[]foriinrange(n):whilestandarr[i]<arr[st[-1]]:# Setting the index of the next smaller element# for the top of the stacknextS[st.pop()]=ist.append(i)returnnextS# Function to find previous smaller for every elementdefprevSmaller(arr):n=len(arr)prevS=[-1]*nst=[]foriinrange(n):whilestandarr[i]<arr[st[-1]]:st.pop()ifst:prevS[i]=st[-1]st.append(i)returnprevS# Function to calculate the maximum rectangular# area in the HistogramdefgetMaxArea(arr):prevS=prevSmaller(arr)nextS=nextSmaller(arr)maxArea=0# Calculate the area for each arrogram barforiinrange(len(arr)):width=nextS[i]-prevS[i]-1area=arr[i]*widthmaxArea=max(maxArea,area)returnmaxAreaif__name__=="__main__":arr=[60,20,50,40,10,50,60]print(getMaxArea(arr))
C#
usingSystem;usingSystem.Collections.Generic;classGfG{// Function to find next smaller for every elementstaticint[]nextSmaller(int[]arr){intn=arr.Length;int[]nextS=newint[n];for(inti=0;i<n;i++){nextS[i]=n;}Stack<int>st=newStack<int>();for(inti=0;i<n;i++){while(st.Count>0&&arr[i]<arr[st.Peek()]){// Setting the index of the next smaller element// for the top of the stacknextS[st.Pop()]=i;}st.Push(i);}returnnextS;}// Function to find previous smaller for every elementstaticint[]prevSmaller(int[]arr){intn=arr.Length;int[]prevS=newint[n];for(inti=0;i<n;i++){prevS[i]=-1;}Stack<int>st=newStack<int>();for(inti=0;i<n;i++){while(st.Count>0&&arr[i]<arr[st.Peek()]){st.Pop();}if(st.Count>0){prevS[i]=st.Peek();}st.Push(i);}returnprevS;}// Function to calculate the maximum rectangular// area in the HistogramstaticintgetMaxArea(int[]arr){int[]prevS=prevSmaller(arr);int[]nextS=nextSmaller(arr);intmaxArea=0;// Calculate the area for each arrogram barfor(inti=0;i<arr.Length;i++){intwidth=nextS[i]-prevS[i]-1;intarea=arr[i]*width;maxArea=Math.Max(maxArea,area);}returnmaxArea;}staticvoidMain(){int[]arr={60,20,50,40,10,50,60};Console.WriteLine(getMaxArea(arr));}}
JavaScript
// Function to find next smaller for every elementfunctionnextSmaller(arr){constn=arr.length;constnextS=newArray(n).fill(n);conststack=[];for(leti=0;i<n;i++){while(stack.length&&arr[i]<arr[stack[stack.length-1]]){// Setting the index of the next smaller element// for the top of the stacknextS[stack.pop()]=i;}stack.push(i);}returnnextS;}// Function to find previous smaller for every elementfunctionprevSmaller(arr){constn=arr.length;constprevS=newArray(n).fill(-1);conststack=[];for(leti=0;i<n;i++){while(stack.length&&arr[i]<arr[stack[stack.length-1]]){stack.pop();}if(stack.length){prevS[i]=stack[stack.length-1];}stack.push(i);}returnprevS;}// Function to calculate the maximum rectangular// area in the HistogramfunctiongetMaxArea(arr){constprevS=prevSmaller(arr);constnextS=nextSmaller(arr);letmaxArea=0;// Calculate the area for each arrogram barfor(leti=0;i<arr.length;i++){constwidth=nextS[i]-prevS[i]-1;constarea=arr[i]*width;maxArea=Math.max(maxArea,area);}returnmaxArea;}// Driver codeconstarr=[60,20,50,40,10,50,60];console.log(getMaxArea(arr));
Output
100
[Optimized Approach] Using Single Stack - O(n) Time and O(n) Space
This approach is mainly an optimization over the previous approach.
The idea is to maintain a stack of bar indices in increasing height order. When a shorter bar is encountered, it means the bar at the top of the stack cannot extend further to the right. We pop it, and using the current index as the right boundary and the new top of the stack as the left boundary, compute the area with the popped bar’s height as the smallest height.
Below are the detailed steps of implementation.
Start with an empty stack and process bars from left to right.
Keep pushing bars into the stack as long as their heights are in non-decreasing order.
When you encounter a bar shorter than the bar at the top of the stack:
The bar at stack.top() cannot extend further to the right.
Pop it from the stack this popped bar’s height becomes the smallest height for its rectangle.
The current index is the right boundary.
The index now at the top of the stack (after popping) gives the previous smaller element, marking the left boundary.
Compute width = right_boundary - left_boundary - 1 and update max area.Continue until the stack is empty or the current bar is taller, then push the current index.
After processing all bars, pop any remaining bars in the stack and Compute width, area, and update the maximum.
C++
#include<iostream>#include<stack>#include<vector>usingnamespacestd;intgetMaxArea(vector<int>&arr){intn=arr.size();stack<int>st;intres=0;inttp,curr;for(inti=0;i<n;i++){while(!st.empty()&&arr[st.top()]>=arr[i]){// The popped item is to be considered as the // smallest element of the Histogramtp=st.top();st.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=st.empty()?i:i-st.top()-1;res=max(res,arr[tp]*width);}st.push(i);}// For the remaining items in the stack, next smaller does// not exist. Previous smaller is the item just below in// stack.while(!st.empty()){tp=st.top();st.pop();curr=arr[tp]*(st.empty()?n:n-st.top()-1);res=max(res,curr);}returnres;}intmain(){vector<int>arr={60,20,50,40,10,50,60};cout<<getMaxArea(arr);return0;}
C
#include<stdio.h>#include<stdlib.h>// Stack structurestructStack{inttop;intcapacity;int*array;};// Function to create a stackstructStack*createStack(intcapacity){structStack*stack=(structStack*)malloc(sizeof(structStack));stack->capacity=capacity;stack->top=-1;stack->array=(int*)malloc(stack->capacity*sizeof(int));returnstack;}intisEmpty(structStack*stack){returnstack->top==-1;}voidpush(structStack*stack,intitem){stack->array[++stack->top]=item;}intpop(structStack*stack){returnstack->array[stack->top--];}intpeek(structStack*stack){returnstack->array[stack->top];}// Function to calculate the maximum rectangular areaintgetMaxArea(intarr[],intn){structStack*st=createStack(n);intres=0,tp,curr;// Traverse all bars of the arrogramfor(inti=0;i<n;i++){// Process the stack while the current element // is smaller than the element corresponding to // the top of the stackwhile(!isEmpty(st)&&arr[peek(st)]>=arr[i]){tp=pop(st);// Calculate width and update resultintwidth=isEmpty(st)?i:i-peek(st)-1;res=(res>arr[tp]*width)?res:arr[tp]*width;}push(st,i);}// Process remaining elements in the stackwhile(!isEmpty(st)){tp=pop(st);curr=arr[tp]*(isEmpty(st)?n:n-peek(st)-1);res=(res>curr)?res:curr;}returnres;}intmain(){intarr[]={60,20,50,40,10,50,60};intn=sizeof(arr)/sizeof(arr[0]);printf("%d\n",getMaxArea(arr,n));return0;}
Java
importjava.util.Stack;classGfG{staticintgetMaxArea(int[]arr){intn=arr.length;Stack<Integer>st=newStack<>();intres=0,tp,curr;for(inti=0;i<n;i++){// Process the stack while the current element // is smaller than the element corresponding to // the top of the stackwhile(!st.isEmpty()&&arr[st.peek()]>=arr[i]){// The popped item is to be considered as the // smallest element of the Histogramtp=st.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=st.isEmpty()?i:i-st.peek()-1;// Update the result if neededres=Math.max(res,arr[tp]*width);}st.push(i);}// For the remaining items in the stack, next smaller does// not exist. Previous smaller is the item just below in// the stack.while(!st.isEmpty()){tp=st.pop();curr=arr[tp]*(st.isEmpty()?n:n-st.peek()-1);res=Math.max(res,curr);}returnres;}publicstaticvoidmain(String[]args){int[]arr={60,20,50,40,10,50,60};System.out.println(getMaxArea(arr));}}
Python
defgetMaxArea(arr):n=len(arr)st=[]res=0foriinrange(n):# Process the stack while the current element # is smaller than the element corresponding to # the top of the stackwhilestandarr[st[-1]]>=arr[i]:# The popped item is to be considered as the # smallest element of the Histogramtp=st.pop()# For the popped item, the previous smaller # element is just below it in the stack (or # the current stack top) and the next smaller # element is iwidth=iifnotstelsei-st[-1]-1# Update the result if neededres=max(res,arr[tp]*width)st.append(i)# For the remaining items in the stack, next smaller does# not exist. Previous smaller is the item just below in# the stack.whilest:tp=st.pop()width=nifnotstelsen-st[-1]-1res=max(res,arr[tp]*width)returnresif__name__=="__main__":arr=[60,20,50,40,10,50,60]print(getMaxArea(arr))
C#
// C# program to find the largest rectangular area possible // in a given histogram usingSystem;usingSystem.Collections.Generic;classGfG{// Function to calculate the maximum rectangular areastaticintgetMaxArea(int[]arr){intn=arr.Length;Stack<int>st=newStack<int>();intres=0,tp,curr;// Traverse all bars of the arrogramfor(inti=0;i<n;i++){// Process the stack while the current element // is smaller than the element corresponding to // the top of the stackwhile(st.Count>0&&arr[st.Peek()]>=arr[i]){tp=st.Pop();// Calculate width and update resultintwidth=st.Count==0?i:i-st.Peek()-1;res=Math.Max(res,arr[tp]*width);}st.Push(i);}// Process remaining elements in the stackwhile(st.Count>0){tp=st.Pop();curr=arr[tp]*(st.Count==0?n:n-st.Peek()-1);res=Math.Max(res,curr);}returnres;}publicstaticvoidMain(){int[]arr={60,20,50,40,10,50,60};Console.WriteLine(getMaxArea(arr));}}
JavaScript
functiongetMaxArea(arr){letn=arr.length;letst=[];letres=0;// Traverse all bars of the arrogramfor(leti=0;i<n;i++){// Process the stack while the current element// is smaller than the element corresponding to// the top of the stackwhile(st.length&&arr[st[st.length-1]]>=arr[i]){lettp=st.pop();// Calculate width and update resultletwidth=st.length===0?i:i-st[st.length-1]-1;res=Math.max(res,arr[tp]*width);}st.push(i);}// Process remaining elements in the stackwhile(st.length){lettp=st.pop();letcurr=arr[tp]*(st.length===0?n:n-st[st.length-1]-1);res=Math.max(res,curr);}returnres;}// Driver codeletarr=[60,20,50,40,10,50,60];console.log(getMaxArea(arr));