Given a histogram represented by an array arr[], where each element denotes the height of a bar and every bar has a uniform width of 1 unit, determine the largest rectangular area that can be formed within the histogram. The rectangle must be constructed from contiguous bars.
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(n^2) Time and O(1) Space
The idea is to expand each bar left and right until you hit a smaller bar, summing its height for each step, and keep track of the maximum area found.
Steps to solve the problem
For every index i, take arr[i] as the smallest height.
Move left and right while bars are ≥ arr[i], adding height of current bar each time.
Update the maximum area after each expansion.
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] By Precomputing Previous and Next Smaller - O(n) Time and O(n) Space
The idea is based on the naive approach. Instead of linearly finding previous smaller and next smaller for every element, we find previous smaller and next smaller for the whole array in linear time.
Step by Step Approach:
Build prevS[] in O(n) time using a stack that holds the index of the previous smaller element for every item in arr[].
Build nextS[] in O(n) time using a stack that holds the index of the next smaller element for every item in arr[].
For each element arr[i] ,Compute width (nextS[i] - prevS[i] - 1) and area = (arr[i] * width).
Compute the maximum area among all computed values
C++
#include<iostream>#include<stack>#include<vector>usingnamespacestd;// Function to find next smaller for every elementvector<int>nextSmaller(vector<int>&arr){intn=arr.size();// Initialize with n for the cases when next smaller// does not existvector<int>nextS(n,n);stack<int>st;// Traverse all array elements from left to rightfor(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();// Initialize with -1 for the cases when prev smaller// does not existvector<int>prevS(n,-1);stack<int>st;// Traverse all array elements from left to rightfor(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);// Initialize with n for the cases// when next smaller does not existfor(inti=0;i<n;i++){nextS[i]=n;}// Traverse all array elements from left to rightfor(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);// Initialize with -1 for the cases when prev smaller does not existfor(inti=0;i<n;i++){prevS[i]=-1;}// Traverse all array elements from left to rightfor(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;// Initialize with n for the cases when next smaller// does not existint[]nextS=newint[n];for(inti=0;i<n;i++){nextS[i]=n;}Stack<Integer>st=newStack<>();// Traverse all array elements from left to rightfor(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;// Initialize with -1 for the cases when prev smaller// does not existint[]prevS=newint[n];for(inti=0;i<n;i++){prevS[i]=-1;}Stack<Integer>st=newStack<>();// Traverse all array elements from left to rightfor(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)# Initialize with n for the cases when next smaller# does not existnextS=[n]*nst=[]# Traverse all array elements from left to rightforiinrange(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)# Initialize with -1 for the cases when prev smaller# does not existprevS=[-1]*nst=[]# Traverse all array elements from left to rightforiinrange(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;// Initialize with n for the cases when next smaller// does not existint[]nextS=newint[n];for(inti=0;i<n;i++){nextS[i]=n;}Stack<int>st=newStack<int>();// Traverse all array elements from left to rightfor(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;// Initialize with -1 for the cases when prev smaller// does not existint[]prevS=newint[n];for(inti=0;i<n;i++){prevS[i]=-1;}Stack<int>st=newStack<int>();// Traverse all array elements from left to rightfor(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;// Initialize with n for the cases when next smaller// does not existconstnextS=newArray(n).fill(n);conststack=[];// Traverse all array elements from left to rightfor(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;// Initialize with -1 for the cases when prev smaller// does not existconstprevS=newArray(n).fill(-1);conststack=[];// Traverse all array elements from left to rightfor(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>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;}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*s=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(s)&&arr[peek(s)]>=arr[i]){tp=pop(s);// Calculate width and update resultintwidth=isEmpty(s)?i:i-peek(s)-1;res=(res>arr[tp]*width)?res:arr[tp]*width;}push(s,i);}// Process remaining elements in the stackwhile(!isEmpty(s)){tp=pop(s);curr=arr[tp]*(isEmpty(s)?n:n-peek(s)-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>s=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(!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;// Update the result if neededres=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// the stack.while(!s.isEmpty()){tp=s.pop();curr=arr[tp]*(s.isEmpty()?n:n-s.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)s=[]res=0foriinrange(n):# Process the stack while the current element # is smaller than the element corresponding to # the top of the stackwhilesandarr[s[-1]]>=arr[i]:# The popped item is to be considered as the # smallest element of the Histogramtp=s.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=iifnotselsei-s[-1]-1# Update the result if neededres=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# the stack.whiles:tp=s.pop()width=nifnotselsen-s[-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>s=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(s.Count>0&&arr[s.Peek()]>=arr[i]){tp=s.Pop();// Calculate width and update resultintwidth=s.Count==0?i:i-s.Peek()-1;res=Math.Max(res,arr[tp]*width);}s.Push(i);}// Process remaining elements in the stackwhile(s.Count>0){tp=s.Pop();curr=arr[tp]*(s.Count==0?n:n-s.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;letstack=[];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(stack.length&&arr[stack[stack.length-1]]>=arr[i]){lettp=stack.pop();// Calculate width and update resultletwidth=stack.length===0?i:i-stack[stack.length-1]-1;res=Math.max(res,arr[tp]*width);}stack.push(i);}// Process remaining elements in the stackwhile(stack.length){lettp=stack.pop();letcurr=arr[tp]*(stack.length===0?n:n-stack[stack.length-1]-1);res=Math.max(res,curr);}returnres;}// Driver codeletarr=[60,20,50,40,10,50,60];console.log(getMaxArea(arr));
Output
100
[Alternate Approach] Using Divide and Conquer - O(n × log n) Time
The idea is to find the minimum value in the given array. Once we have index of the minimum value, the max area is maximum of following three values.
Maximum area in left side of minimum value (Not including the min value)
Maximum area in right side of minimum value (Not including the min value)