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.
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'.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.
prefix[r][c] is the sum of all elements in the sub-matrix from (0,0) to (r-1,c-1).(r1, r2) and every pair of columns (c1, c2), compute the sum of the rectangle using the prefix sum.(r2 - r1 + 1) * (c2 - c1 + 1), all cells are 1. Update the maximum area.Input:
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.
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.
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:
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.
Every all-1 rectangle has a bottom edge that sits on some row r. For a rectangle whose bottom edge is row r, its height in column c equals the number of consecutive '1's ending at row r in that column, which is exactly the histogram height we compute for row r. So iterating the histogram over every possible base row covers every rectangle, and the largest one is found.
Within one histogram, the widest rectangle that uses a given bar at its full height extends left until the first strictly shorter bar and right until the first strictly shorter bar. The stack holds bar indices in increasing height order, so when a shorter bar arrives at index i, popping a bar of height h gives the right boundary as i and the left boundary as the new stack top, making the width i - stack.top - 1.
heights array of length cols, all zeros.heights: if matrix[row][col] == '1', increment heights[col] by 1. Otherwise, reset heights[col] to 0.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.
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.
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.
width array of size rows x cols.(r, c):matrix[r][c] == '0', set width[r][c] = 0.width[r][c] = width[r][c-1] + 1 (or 1 if c == 0).(r, c) where width[r][c] > 0:minWidth = width[r][c].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.