84-largest-rectangle-in-histogram¶
Try it on leetcode
Description¶
Given an array of integers heights
representing the histogram's bar height where the width of each bar is 1
, return the area of the largest rectangle in the histogram.
Example 1:

Input: heights = [2,1,5,6,2,3] Output: 10 Explanation: The above is a histogram where width of each bar is 1. The largest rectangle is shown in the red area, which has an area = 10 units.
Example 2:

Input: heights = [2,4] Output: 4
Constraints:
1 <= heights.length <= 105
0 <= heights[i] <= 104
Solution(Python)¶
class Solution:
"""
for calculating a rectangle we need both width and height
the width of the rectangle will be the difference of index positions
and height will be the corresponding values
Constraints:
* 1 <= heights.length <= 10^5
* 0 <= heights[i] <= 10^4
1.Bruteforce:
*we can start from every possible recatngles that can be formed from the given
array
*with respect to width we can make upto n^2 possible
*while considering the height choose the rectangle with less height
Implementation:
maxRectangleArea
for i in n:
for j in n:
maxRectangleArea = max(maxRectangleArea, (j-i+1) * min(arr[i],arr[j]) )
Analysis:
Time Complexity: O(n^2)
Space Complexity: O(1)
2. presum:
Idea:
bruteforcs can be written as
for each index:
maxarea = max(height[index]*(leftindex[i] - rightindex[i]))
with precached the leftsmallest index and right smallest index
we can optmize the bruteforce method
for leftsmallest index move until we hit the smallest height
similary for right smallest index repeat the process
Analysis:
Time Complexity: O(n)
Space Complexity: O(n)
3. stacks:
in presum technique we only cache the information of bars in increaing heights
instead of using two separate arrays to store it's value
we can use a stack of bars we identified so far with only bars greater than current bar
Analysis:
Time Complexity: O(n)
Space Complexity: O(n)
"""
def largestRectangleArea(self, heights: List[int]) -> int:
return self.stack(heights)
def bruteforce(self, heights: List[int]) -> int:
n = len(heights)
maxRec = float("-INF")
for i in range(n):
curHeight = heights[i]
for j in range(i, n):
curHeight = min(curHeight, heights[j])
maxRec = max(maxRec, abs(j - i + 1) * curHeight)
return maxRec
def presum(self, heights: List[int]) -> int:
n = len(heights)
left = [0] * n
right = [0] * n
left[0] = -1
right[n - 1] = n
for i in range(1, n):
curr = i - 1
while curr >= 0 and heights[i] <= heights[curr]:
curr = left[curr]
left[i] = curr
for i in range(n - 2, -1, -1):
curr = i + 1
while curr <= n - 1 and heights[i] <= heights[curr]:
curr = right[curr]
right[i] = curr
maxRec = float("-INF")
for i in range(n):
maxRec = max(maxRec, heights[i] * (right[i] - left[i] - 1))
return maxRec
def stack(self, heights: List[int]) -> int:
heights.append(0)
stack = []
maxRec = 0
n = len(heights)
for i in range(n):
height = heights[i]
while stack and heights[stack[-1]] >= height:
H = heights[stack.pop()]
W = i if not stack else i - stack[-1] - 1
maxRec = max(maxRec, H * W)
stack.append(i)
return maxRec