The Largest Rectangle in Histogram is one of the most elegant monotonic stack problems—and one of the easiest to get wrong.
Three critical mistakes cause 90% of wrong answers. Understanding and fixing them is the difference between AC (Accepted) and WA (Wrong Answer).
This guide shows you the exact mistakes, why they happen, and how to fix them permanently.
TL;DR
The 3 critical mistakes:
- Wrong width calculation (
i - stack[-1]instead ofi - stack[-1] - 1) - Missing sentinels (not adding 0 at both ends)
- Wrong stack order (decreasing instead of increasing)
Quick fixes:
# Fix 1: Correct width
width = i - stack[-1] - 1 # Exclude boundaries
# Fix 2: Add sentinels
heights = [0] + heights + [0]
# Fix 3: Increasing stack
while stack and heights[i] < heights[stack[-1]]:
# Process...Mistake 1: Wrong Width Calculation
The Bug
❌ Wrong:
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
height = heights[h_idx]
width = i - stack[-1] # WRONG!
area = height * widthWhy It's Wrong
The boundaries are NOT included in the rectangle.
Visual:
Heights: [2, 1, 5, 6, 2, 3]
[0 1 2 3 4 5]
Processing i=4 (height=2), popping index 3 (height=6):
Left boundary: stack[-1] = 2 (height=5)
Right boundary: i = 4 (height=2)
Rectangle with height 6:
Can only extend between boundaries
NOT including boundaries
Correct width: 4 - 2 - 1 = 1
Wrong width: 4 - 2 = 2 (includes boundary!)The Fix
✅ Correct:
width = i - stack[-1] - 1 # Subtract 1 to exclude boundariesWhy -1?
stack[-1]is the left boundary (next smaller to left)iis the right boundary (next smaller to right)- Rectangle extends between boundaries, not including them
- Distance between positions:
right - left - 1
Complete Example
def largestRectangleArea(heights):
heights = [0] + heights + [0]
stack = []
max_area = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
height = heights[h_idx]
# CORRECT: Exclude boundaries
width = i - stack[-1] - 1
area = height * width
max_area = max(max_area, area)
stack.append(i)
return max_areaMistake 2: Missing Sentinels
The Bug
❌ Wrong:
def largestRectangleArea(heights):
stack = []
max_area = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
# What if stack is empty?
if not stack:
width = i # Special case
else:
width = i - stack[-1] - 1
area = heights[h_idx] * width
max_area = max(max_area, area)
stack.append(i)
# What about remaining elements in stack?
while stack:
h_idx = stack.pop()
if not stack:
width = len(heights)
else:
width = len(heights) - stack[-1] - 1
area = heights[h_idx] * width
max_area = max(max_area, area)
return max_areaProblems:
- Complex edge case handling
- Easy to make off-by-one errors
- Need to process remaining stack separately
The Fix: Add Sentinels
✅ Correct:
def largestRectangleArea(heights):
# Add sentinels: 0 at both ends
heights = [0] + heights + [0]
stack = []
max_area = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
height = heights[h_idx]
width = i - stack[-1] - 1
area = height * width
max_area = max(max_area, area)
stack.append(i)
# No need to process remaining stack
# Sentinels ensure all bars are processed
return max_areaWhy Sentinels Work
Left sentinel (0 at start):
- Ensures stack is never empty when calculating width
- Acts as left boundary for all bars
Right sentinel (0 at end):
- Forces all remaining bars to be processed
- Acts as right boundary for all bars
Visual:
Original: [2, 1, 5, 6, 2, 3]
With sentinels: [0, 2, 1, 5, 6, 2, 3, 0]
[0 1 2 3 4 5 6 7]
When processing right sentinel (i=7, height=0):
All bars in stack are popped
Stack always has at least index 0 (left sentinel)
No special case handling neededMistake 3: Wrong Stack Order
The Bug
❌ Wrong:
# Using decreasing stack (wrong for histogram!)
while stack and heights[i] > heights[stack[-1]]:
# This finds next GREATER, not next SMALLER
stack.pop()Why It's Wrong
For histogram, we need INCREASING stack to find next smaller elements.
Reasoning:
- Rectangle height is limited by the shortest bar
- We need to find when a shorter bar appears
- Shorter bar = next SMALLER element
- Next smaller requires INCREASING stack
The Fix
✅ Correct:
# Use increasing stack
while stack and heights[i] < heights[stack[-1]]:
# Pop when current is SMALLER
h_idx = stack.pop()
# Calculate area with h_idx as heightComparison
| Problem | Stack Order | Popping Condition |
|---|---|---|
| Next Greater Element | Decreasing | nums[i] > stack[-1] |
| Histogram | Increasing | heights[i] < stack[-1] |
| Next Smaller Element | Increasing | nums[i] < stack[-1] |
Complete Correct Solution
def largestRectangleArea(heights):
"""
LeetCode #84: Largest Rectangle in Histogram
Approach: Monotonic increasing stack
- For each bar, find next smaller on both sides
- Calculate area with current bar as height
Time: O(n)
Space: O(n)
"""
# Add sentinels
heights = [0] + heights + [0]
stack = []
max_area = 0
for i in range(len(heights)):
# Increasing stack: pop when current is smaller
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
height = heights[h_idx]
# Width: exclude boundaries
width = i - stack[-1] - 1
area = height * width
max_area = max(max_area, area)
stack.append(i)
return max_area
# Test
print(largestRectangleArea([2, 1, 5, 6, 2, 3]))
# Output: 10Step-by-Step Trace
Heights: [0, 2, 1, 5, 6, 2, 3, 0]
[0 1 2 3 4 5 6 7]
i=0, h=0: stack=[0]
i=1, h=2: 2 > 0, stack=[0,1]
i=2, h=1:
1 < 2, pop 1, height=2, width=2-0-1=1, area=2×1=2
1 > 0, stack=[0,2]
i=3, h=5: 5 > 1, stack=[0,2,3]
i=4, h=6: 6 > 5, stack=[0,2,3,4]
i=5, h=2:
2 < 6, pop 4, height=6, width=5-3-1=1, area=6×1=6
2 < 5, pop 3, height=5, width=5-2-1=2, area=5×2=10 ← MAX
2 > 1, stack=[0,2,5]
i=6, h=3: 3 > 2, stack=[0,2,5,6]
i=7, h=0:
0 < 3, pop 6, height=3, width=7-5-1=1, area=3×1=3
0 < 2, pop 5, height=2, width=7-2-1=4, area=2×4=8
0 < 1, pop 2, height=1, width=7-0-1=6, area=1×6=6
stack=[0]
Maximum area: 10 ✓Edge Cases
Edge Case 1: Single Bar
heights = [5]
# With sentinels: [0, 5, 0]
# Area: 5 × 1 = 5 ✓Edge Case 2: All Same Height
heights = [3, 3, 3, 3]
# Maximum: 3 × 4 = 12 ✓Edge Case 3: Strictly Increasing
heights = [1, 2, 3, 4, 5]
# Maximum: 3 × 3 = 9 (middle bar)Edge Case 4: Strictly Decreasing
heights = [5, 4, 3, 2, 1]
# Maximum: 5 × 1 = 5 (tallest bar)Debugging Checklist
When your histogram solution fails:
-
Width calculation: Using
i - stack[-1] - 1? -
Sentinels: Added 0 at both ends?
-
Stack order: Increasing (not decreasing)?
-
Popping condition:
<(not>)? -
Edge cases: Tested single bar, all same, increasing, decreasing?
Related Problems
Same pattern:
- Maximal Rectangle (#85) - 2D histogram
- Largest Rectangle in Histogram (#84) - Original
- Maximum Binary Tree (#654) - Tree construction
Conclusion
Histogram problems have 3 critical mistakes that cause most failures.
The fixes:
- Width:
i - stack[-1] - 1(exclude boundaries) - Sentinels:
[0] + heights + [0](simplify edge cases) - Stack order: Increasing (for next smaller)
The template:
heights = [0] + heights + [0]
stack = []
max_area = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h_idx = stack.pop()
height = heights[h_idx]
width = i - stack[-1] - 1
area = height * width
max_area = max(max_area, area)
stack.append(i)
return max_areaMaster these fixes, and you'll never fail histogram problems again.
Next steps:
Want to Practice LeetCode Smarter?
LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.
Also compatible with Edge, Brave, and Opera
