Algorithm

Maximal Rectangle

Monotonic Stack Pattern

Maximal Rectangle

Given a rows x cols binary matrix filled with '0's and '1's, find the largest rectangle containing only '1's and return its area.

CONSTRAINTS
  • rows == matrix.length
  • cols == matrix[i].length
  • 1 <= rows, cols <= 200
  • matrix[i][j] is '0' or '1'
EXAMPLE 1
Input: matrix = [['1','0','1','0','0'],['1','0','1','1','1'],['1','1','1','1','1'],['1','0','0','1','0']]
Output: 6
The central 3x2 block of ones at indices (1,2) to (2,4) forms the largest rectangle.
Do we need the logic from Largest Rectangle in Histogram?
Yes. This problem is effectively a 'wrapper' around the histogram problem. The core observation is that a 2D matrix of ones is just a set of stacked histograms.

A rectangle of all 1s in a 2D grid sounds much harder than any 1D problem, until you slice it by rows. Treat each row as the ground and look at the columns standing on it: a column's "bar height" is how many consecutive 1s stack up directly above that cell, ending on this row. A 0 snaps that column's height back to 0, because no all-1s rectangle can pass through a 0. Now the biggest all-1s rectangle whose bottom edge rests on this row is exactly the largest rectangle in this row's bar chart. Sweep the rows top to bottom, updating the heights as you go, and the answer is the best row-histogram you ever see.

So the whole problem reduces to solving "largest rectangle in a histogram" once per row. Here's how that 1D solve works, since it carries all the weight. Any rectangle in a histogram is limited by its shortest bar, so for each bar we want the widest span where it is the shortest — bounded on each side by the nearest strictly shorter bar. Finding those nearest-shorter neighbors in one pass is the job of a monotonic stack: a normal push/pop stack whose bar heights we keep increasing from bottom to top. Scanning left to right, when the current bar is shorter than the one on top, the current column is that top bar's right wall — pop it, its left wall is the new top (nearest shorter bar to its left, because the stack rises), and its area is height × (right − left − 1). Keep popping while the current bar stays shorter, then push. A height-0 sentinel at the end flushes whatever's left.

python
def maximal_rectangle(matrix):
    if not matrix:
        return 0
    cols = len(matrix[0])
    heights = [0] * cols
    best = 0
    for row in matrix:
        for c in range(cols):
            heights[c] = heights[c] + 1 if row[c] == '1' else 0   # grow, or reset on a 0
        best = max(best, largest_in_histogram(heights))
    return best

def largest_in_histogram(heights):
    bars = heights + [0]        # sentinel forces every remaining bar to be measured
    stack = [-1]                # sentinel left wall
    best = 0
    for i in range(len(bars)):
        while len(stack) > 1 and bars[i] < bars[stack[-1]]:
            h = bars[stack.pop()]
            w = i - stack[-1] - 1
            best = max(best, h * w)
        stack.append(i)
    return best

Each row costs one linear histogram pass (every column pushed and popped once), so the total work is proportional to the number of cells in the grid.

Worked Example:[['1','0'], ['1','1']]
- Row 0 ['1','0'] → heights [1, 0]; largest histogram rectangle is 1.
- Row 1 ['1','1'] → heights [2, 1]; the height-1 bar spans both columns for area 2, beating the lone height-2 bar.
- Best overall: 2.
Interactive Strategy Visualization
MATRIX REDUCTION INSIGHT

2D Matrix to Histogram Strategy

Processing Row 0
1
0
1
0
1
1
1
1
1
1
1
0
Histogram View
1
1

Key Strategy

1

Histogram Evolution: At each row, update heights based on consecutive 1s.

2

Monotonic Stack: Solve the Largest Rectangle in Histogram for each row.

Complexity
TimeO(N × M)
SpaceO(M)
TIP

Dynamic Reduction

The core insight is to transform the 2D grid problem into multiple 1D histogram problems. For each row, calculate how many consecutive '1's exist ending at that cell.

O((R × C)²) Brute Force
O(R² × C) Row Prefixes
O(R × C) Histogram + Monotonic Stack