AlgoMaster Logo

Maximal Rectangle

hardFrequencyUpdated September 21, 2026

Understanding the Problem

We have a 2D grid of characters where each cell is either '1' or '0'. We need to find the largest axis-aligned rectangle that contains only '1's and return its area.

A brute force approach tries every possible rectangle defined by a top-left and bottom-right corner, then checks whether all cells inside are '1'. That is slow. The faster idea is to reduce this 2D problem to something solvable in linear time per row.

Reading the matrix row by row, we can build a histogram of heights. For each cell (r, c), the height is the number of consecutive '1's ending at row r in column c. Finding the largest rectangle in a single row's histogram is the "Largest Rectangle in Histogram" problem, solvable in O(cols) time using a stack. Solving it for every row and taking the maximum gives the answer.

Key Constraints:

  • 1 <= rows, cols <= 200 → At most 40,000 cells. An O(rows cols^2) solution does about 8 million operations and passes, but the brute-force O(rows^2 cols^2) (around 1.6 billion) is too slow, so we need at least the histogram or DP approach.
  • matrix[i][j] is '0' or '1' → The cells are characters, not integers, so each comparison and sum has to convert from '1'/'0'.

Approach 1: Brute Force (Prefix Sum)

Intuition

Try every possible rectangle in the matrix and check if it contains only '1's. A rectangle is defined by its top-left corner (r1, c1) and bottom-right corner (r2, c2). For each one, we verify that every cell inside is '1'.

Scanning every cell of every rectangle would add another factor of rows * cols, so we use a 2D prefix sum instead. With the prefix sum precomputed, checking whether a rectangle is all '1's is O(1): if the sum over the rectangle equals its area, every cell in it is 1.

Even with this optimization, we still enumerate all O(rows^2 * cols^2) possible rectangles, which is about 1.6 billion for a 200x200 matrix.

Algorithm

  1. Convert the character matrix to an integer matrix (0s and 1s).
  2. Build a 2D prefix sum array where prefix[r][c] is the sum of all elements in the sub-matrix from (0,0) to (r-1,c-1).
  3. For every pair of rows (r1, r2) and every pair of columns (c1, c2), compute the sum of the rectangle using the prefix sum.
  4. If the sum equals (r2 - r1 + 1) * (c2 - c1 + 1), all cells are 1. Update the maximum area.
  5. Return the maximum area found.

Example Walkthrough

Input:

0
1
2
3
4
0
1
0
1
0
0
1
1
0
1
1
1
2
1
1
1
1
1
3
1
0
0
1
0
matrix

We build the prefix sum first, then enumerate rectangles. Using 1-indexed prefix coordinates, the rectangle with (r1, c1) = (2, 3) and (r2, c2) = (3, 5) covers the original cells in rows 1-2, columns 2-4 (the block of six 1s in the bottom-right). Its prefix sum is prefix[3][5] - prefix[1][5] - prefix[3][2] + prefix[1][2] = 6, and its area is (3 - 2 + 1) * (5 - 3 + 1) = 2 * 3 = 6. Sum equals area, so every cell is 1, and maxArea becomes 6.

Other rectangles update maxArea along the way: the single cells give area 1, the full first column gives a 4 * 1 all-1 strip of area 4, and the 1 1 1 block in row 2 gives area 3. None of the all-1 rectangles exceeds 6. After the four nested loops finish, the answer is 6.

6
maxArea

Code

Enumerating all rectangles is too slow for large matrices. The next approach treats each row as a histogram and finds the largest rectangle in that histogram in linear time.

Approach 2: Histogram with Monotonic Stack

Intuition

Process the matrix one row at a time, from top to bottom. For each column, track a height: the number of consecutive '1's ending at the current row. A '0' resets the height to 0, and a '1' makes the height one more than the height in that column at the row above.

Each row's heights form a histogram. The largest rectangle in a histogram is computable in O(cols) with a monotonic stack. Running that over every row's histogram and taking the maximum gives the answer.

For the matrix from Example 1, the per-row histograms are:

  • Row 0: heights = [1, 0, 1, 0, 0], max rect = 1
  • Row 1: heights = [2, 0, 2, 1, 1], max rect = 3
  • Row 2: heights = [3, 1, 3, 2, 2], max rect = 6
  • Row 3: heights = [4, 0, 0, 3, 0], max rect = 4

The monotonic stack finds the largest rectangle in a histogram by keeping bar indices in increasing height order. When a shorter bar appears, the taller bars on the stack can no longer extend further right, so we pop them and compute the area each one anchors.

Algorithm

  1. Initialize a heights array of length cols, all zeros.
  2. For each row in the matrix:
    • Update heights: if matrix[row][col] == '1', increment heights[col] by 1. Otherwise, reset heights[col] to 0.
    • Compute the largest rectangle in the current histogram using a monotonic stack.
    • Update the global maximum area.
  3. Return the global maximum area.

The monotonic stack sub-routine iterates through indices 0 to cols (using a sentinel height of 0 at the end). When the current height is less than the top of the stack, we pop and compute area = height * width, where width extends from the current position back to the new stack top.

Example Walkthrough

1Initial heights = [0, 0, 0, 0, 0]
0
0
1
0
2
0
3
0
4
0
1/9

Code

This approach is optimal at O(rows * cols), though it relies on the monotonic stack sub-routine. The next approach solves the problem with dynamic programming alone, trading some time for a stack-free implementation.

Approach 3: Dynamic Programming (Width-Based)

Intuition

This approach uses dynamic programming without a stack. For each cell (r, c) that contains '1', compute the width: the number of consecutive '1's ending at column c in row r, counting leftward. To find the largest rectangle whose bottom-right corner is (r, c), expand upward row by row. As the rectangle grows taller, its usable width can only shrink to the minimum width seen across the rows it spans, since every row in the rectangle must be at least that wide. At each row, the candidate area is min_width * height, and we keep the maximum.

For example, if cell (2, 4) has width 5 and cell (1, 4) has width 3, then a rectangle of height 2 anchored at (2, 4) has width min(5, 3) = 3, giving area 6.

Algorithm

  1. Create a width array of size rows x cols.
  2. For each cell (r, c):
    • If matrix[r][c] == '0', set width[r][c] = 0.
    • Otherwise, width[r][c] = width[r][c-1] + 1 (or 1 if c == 0).
  3. For each cell (r, c) where width[r][c] > 0:
    • Set minWidth = width[r][c].
    • Expand upward from row r to row 0. At each row k, update minWidth = min(minWidth, width[k][c]). If minWidth == 0, stop. Compute area = minWidth * (r - k + 1) and update the global max.
  4. Return the global maximum area.

Example Walkthrough

1Initialize width matrix to all zeros
0
1
2
3
4
0
0
0
0
0
0
1
0
0
0
0
0
2
0
0
0
0
0
3
0
0
0
0
0
1/8

Code