Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find largest rectangle area under histogram in python
A histogram is a graphical representation where data is displayed using bars of different heights. The largest rectangle area problem asks us to find the maximum rectangular area that can be formed under the histogram bars.
Given a list of heights representing histogram bars, we need to find the area of the largest rectangle that fits completely under the bars.
Problem Example
For the input nums = [3, 2, 5, 7], the histogram looks like:
The largest rectangle has height 2 and width 5, giving an area of 10.
Algorithm Approach
We use a stack-based approach to solve this efficiently in O(n) time ?
- Use a stack to store indices of histogram bars
- For each bar, pop bars from stack that are taller than current bar
- Calculate area using the popped bar as the smallest height
- Keep track of maximum area found
Implementation
def largest_rectangle_area(heights):
stack = [-1] # Initialize with sentinel value
heights.append(0) # Add sentinel to process remaining bars
max_area = 0
for i in range(len(heights)):
# Pop bars taller than current bar
while heights[i] < heights[stack[-1]]:
height = heights[stack.pop()]
width = i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
return max_area
# Test the function
histogram = [3, 2, 5, 7]
result = largest_rectangle_area(histogram.copy()) # Use copy to preserve original
print(f"Histogram: {histogram}")
print(f"Largest rectangle area: {result}")
Histogram: [3, 2, 5, 7] Largest rectangle area: 10
How It Works
Let's trace through the algorithm step by step ?
def largest_rectangle_area_verbose(heights):
stack = [-1]
heights.append(0)
max_area = 0
print(f"Processing heights: {heights}")
for i in range(len(heights)):
print(f"\nStep {i}: Processing height {heights[i]} at index {i}")
print(f"Stack before: {stack}")
while stack and heights[i] < heights[stack[-1]]:
height = heights[stack.pop()]
width = i - stack[-1] - 1
area = height * width
max_area = max(max_area, area)
print(f" Popped height {height}, width {width}, area {area}")
stack.append(i)
print(f"Stack after: {stack}, Max area so far: {max_area}")
return max_area
# Trace execution
histogram = [3, 2, 5, 7]
result = largest_rectangle_area_verbose(histogram.copy())
Processing heights: [3, 2, 5, 7, 0] Step 0: Processing height 3 at index 0 Stack before: [-1] Stack after: [-1, 0], Max area so far: 0 Step 1: Processing height 2 at index 1 Stack before: [-1, 0] Popped height 3, width 1, area 3 Stack after: [-1, 1], Max area so far: 3 Step 2: Processing height 5 at index 2 Stack before: [-1, 1] Stack after: [-1, 1, 2], Max area so far: 3 Step 3: Processing height 7 at index 3 Stack before: [-1, 1, 2] Stack after: [-1, 1, 2, 3], Max area so far: 3 Step 4: Processing height 0 at index 4 Stack before: [-1, 1, 2, 3] Popped height 7, width 1, area 7 Popped height 5, width 2, area 10 Popped height 2, width 4, area 8 Stack after: [-1], Max area so far: 10
Alternative Solutions
Brute Force Approach
def largest_rectangle_brute_force(heights):
max_area = 0
n = len(heights)
for i in range(n):
min_height = heights[i]
for j in range(i, n):
min_height = min(min_height, heights[j])
width = j - i + 1
area = min_height * width
max_area = max(max_area, area)
return max_area
# Compare approaches
histogram = [3, 2, 5, 7]
print(f"Brute force result: {largest_rectangle_brute_force(histogram)}")
print(f"Stack approach result: {largest_rectangle_area(histogram.copy())}")
Brute force result: 10 Stack approach result: 10
Complexity Analysis
| Approach | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Stack-based | O(n) | O(n) | Optimal solution |
| Brute Force | O(n²) | O(1) | Understanding concept |
Conclusion
The stack-based approach efficiently solves the largest rectangle in histogram problem in linear time. The key insight is using a stack to track potential rectangle boundaries and calculating areas when we encounter shorter bars.
