Maximal Rectangle
Given a binary matrix, find the largest rectangle containing only 1s and return its area.
Open on LeetCode ↗Intuition
The trap is treating this as its own 2D problem instead of recognizing it as Largest Rectangle in Histogram wearing a matrix costume. Treat every row as the ground line of a histogram, where each bar's height is the number of consecutive 1s stacked directly above that column — the largest rectangle in the matrix with its bottom on this row is then the largest rectangle in that histogram, solved in O(n) with a monotonic stack. Run it once per row and take the best over all rows.
Each row becomes a histogram: the height at a column is how many consecutive 1s sit above it. Then Largest Rectangle in Histogram runs once per row. Reducing a 2-D problem to a known 1-D one, row by row, is the transferable move.
Approach
Build the histogram row by row
Keep a heights array of width n. For each row, heights[j] += 1 when the cell is 1 — but the easy-to-miss half is heights[j] = 0 when it is 0, not just skipping the increment. A single zero breaks the column's vertical run completely, so the height resets to 0 rather than freezing at whatever it was; forgetting the reset silently treats a broken column as still standing and inflates every rectangle above it. This is a small DP carried across rows in O(1) extra space per step.
Reuse Largest Rectangle in Histogram
For each histogram, a monotonic increasing stack finds, for every bar, the nearest smaller bar on each side. The rectangle with that bar as its limiting height spans between those boundaries, giving area height * (right - left - 1). Take the maximum over all bars.
Take the maximum across rows
Every rectangle of 1s has a bottom row, and when that row is processed the rectangle appears in its histogram — so no rectangle is missed. With m rows and n columns the total is O(mn) time and O(n) space, versus O(m^2 n^2) for the naive enumeration. The prerequisite really is Largest Rectangle in Histogram; without it this looks unapproachable.
Solution & live demo
Common pitfalls
Not resetting the height on a zero
if row[j] == '1': heights[j] += 1
heights[j] = heights[j] + 1 if row[j] in (1, '1') else 0
A zero breaks the vertical run, so the accumulated height above it can no longer support a rectangle at this row. Leaving the old value lets rectangles span straight through obstacles.
Omitting the sentinel column
for j in range(n):
for j in range(n + 1):
h = heights[j] if j < n else 0Bars still on the stack when the scan ends never get measured. A virtual zero-height column at the end forces every remaining bar to pop and be evaluated.
Computing the width from the popped index
best = max(best, ht * (j - st[-1]))
left = st[-1] if st else -1 best = max(best, ht * (j - left - 1))
The rectangle spans from just after the new stack top to just before j, giving a width of j - left - 1. Using the popped index measures only part of the span, and an empty stack means the bar extends all the way to the left edge.
Edge cases
Return 0 before any processing.
The heights array stays flat at zero and 0 is returned.
The answer is the full area, m * n.
It degenerates to plain largest-rectangle-in-histogram on a 0/1 array.