I understand how to solve the Largest Rectangle in Histogram in O(N^2) by expanding left and right from every bar. But top interviewers and competitive programming platforms always expect the O(N) single-pass Monotonic Stack solution.
Every explanation I read online just dumps a while loop with stack pops without clearly explaining why the stack width formula i - stack[-1] - 1 works. Can someone break down the exact mental model like I’m a junior engineer?
The Largest Rectangle in Histogram is famous because it feels like magic until you see the visual geometry behind it. Let’s demystify it once and for all.
1. The Core Realization
For any bar at index
kwith heightH = heights[k], what is the widest rectangle you can make usingHas the height?The rectangle can extend as far left as possible until it hits a bar shorter than
H, and as far right as possible until it hits another bar shorter thanH.So the entire problem boils down to finding two things for every bar:
2. Why a Monotonic Increasing Stack?
A monotonic stack keeps indices of bars whose heights are strictly increasing:
[2, 4, 6, 8].As long as the next bar is taller or equal, the rectangle could potentially keep growing, so we just push its index onto the stack.
The Trigger: The moment you encounter a bar that is shorter than the top of the stack (say we see a bar of height
3when the stack top is8), you have found the Right Boundary for that8! The bar of height8cannot extend any further to the right. Its journey is finished.When you pop
8:iis its first shorter bar on the right.Therefore, the width of the rectangle bounded by height
His simply:width = (i - stack[-1] - 1).3. Clean Python 3.12 Implementation with Sentinel Trick
4. Step-by-Step Trace with Numbers
Let’s trace
heights = [2, 1, 5, 6, 2, 3]with sentinel[2, 1, 5, 6, 2, 3, 0]:i = 0 (h=2): Stack =[0]i = 1 (h=1): 1 < 2! Pop0(h=2). Stack empty → width = 1. Area =2 * 1 = 2. Push 1. Stack =[1].i = 2 (h=5): 5 > 1. Push 2. Stack =[1, 2].i = 3 (h=6): 6 > 5. Push 3. Stack =[1, 2, 3].i = 4 (h=2): 2 < 6!3(h=6): right = 4, left = 2 → width =4 - 2 - 1 = 1. Area =6 * 1 = 6.2(h=5): right = 4, left = 1 → width =4 - 1 - 1 = 2. Area =5 * 2 = 10!Push 4. Stack =
[1, 4].0sentinel cleanly flushes all remaining elements.Max Area = 10 (from bars of height 5 and 6).
5. Why is this strictly O(N)?
Even though there is a
whileloop inside theforloop, every index is pushed onto the stack exactly once and popped from the stack at most once. Total operations across the entire array are at most2N. That is a rock-solid, linearO(N)runtime withO(N)memory.