Python 0085.py
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
height = len(matrix)
width = len(matrix[0])
# str => int
for y in range(height):
for x in range(width):
matrix[y][x] = int(matrix[y][x])
# prefix sum
for y in range(height):
for x in range(1, width):
if matrix[y][x] != 0 and matrix[y][x-1] != 0:
matrix[y][x] += matrix[y][x-1]
result = 0
for x in range(width):
for y in range(height):
w = width
h = 0
for scan in range(y, height):
if matrix[scan][x] == 0:
break
w = min(w, matrix[scan][x])
h += 1
result = max(result, w*h)
return result
Difficulty
and has an acceptance rate of about 59% (1+ million submissions).
Typical patterns to solve this problem:
- Array
- Dynamic Programming
- Matrix
- Monotonic Stack
- Stack
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The implementation computes the area of the largest rectangle consisting solely of 1s in a binary matrix. It proceeds in three distinct phases: conversion of the input from strings to integers, construction of a horizontal prefix sum that records consecutive 1s in each row, and a double-nested scan that expands vertically while tracking the minimal width encountered. The result is the maximal product of width and height observed during the scan.
Conversion of Input Types
The first nested loops replace each character '0' or '1' with its numeric counterpart. By performing the conversion in place, the algorithm avoids allocating an auxiliary structure.
for y in range(height):
for x in range(width):
matrix[y][x] = int(matrix[y][x])
This step guarantees that subsequent arithmetic operations work directly on integer values, simplifying the logic for the prefix-sum phase.
Prefix Sum Construction
The second pair of loops builds a running count of consecutive 1s to the left of each cell. When a cell and its immediate left neighbor are both non-zero, the current cell accumulates the left neighbor’s count. The operation is also performed in place, reusing the original matrix storage.
for y in range(height):
for x in range(1, width):
if matrix[y][x] != 0 and matrix[y][x-1] != 0:
matrix[y][x] += matrix[y][x-1]
After this phase, each entry holds the length of the longest horizontal stretch of 1s ending at that column for its row. This compact representation enables the later vertical scan to retrieve width information instantly without recomputing row-wise runs.
Main Scanning Loop
The core of the algorithm iterates column by column, then row by row, expanding a vertical window downward from each starting cell. Two variables, w (current minimal width) and h (current height), are updated as the scan proceeds. If a zero is encountered, the inner vertical scan terminates early, preventing unnecessary work.
result = 0
for x in range(width):
for y in range(height):
w = width
h = 0
for scan in range(y, height):
if matrix[scan][x] == 0:
break
w = min(w, matrix[scan][x])
h += 1
result = max(result, w*h)
The inner loop maintains w as the smallest horizontal run among the rows visited so far, ensuring that any rectangle considered is fully composed of 1s. Multiplying w by the current height h yields the area of the candidate rectangle, and result retains the largest area found.
Edge Cases Handled
When the matrix contains only zeros, the prefix-sum phase leaves all entries at zero, causing the vertical scan to break immediately at each starting cell; the final result remains zero, correctly indicating the absence of any rectangle of 1s.
A single-row matrix is processed without special treatment: the prefix sum records the lengths of consecutive 1s, and the vertical scan runs only one iteration, yielding the maximal horizontal stretch as the area.
Similarly, a single-column matrix bypasses the horizontal prefix accumulation (since the inner loop starts at index 1) and relies on the vertical scan to count consecutive 1s, producing the correct maximal vertical length.
The conversion step also tolerates matrices where each element is already an integer; the int() cast is idempotent, leaving the values unchanged.
Performance Optimizations
The algorithm reuses the input matrix for both type conversion and prefix-sum storage, eliminating the need for extra arrays and reducing memory pressure.
By updating the width w with min(w, matrix[scan][x]) during the vertical expansion, the code avoids recomputing the minimum across the visited rows after each step, achieving constant-time updates.
The early break when a zero is encountered in the vertical scan prevents the inner loop from traversing rows that cannot contribute to a valid rectangle, cutting off unnecessary iterations especially in sparse matrices.
Limiting the initial width w to the total number of columns (width) provides a safe upper bound that is quickly tightened as soon as the first row is examined, ensuring that the multiplication w*h never overestimates the feasible area.
Overall, the in-place transformations and early termination conditions combine to keep the execution tight and memory-efficient while still exploring all viable rectangle configurations.
ELI5 - Simplified Explanation
Imagine you have a big sheet of graph paper filled with little squares. Some squares are colored black and some are left empty. The goal is to find the biggest rectangle you can draw using only the empty squares.
First, the computer looks at every single square on the paper. It turns the text labels into numbers so it can do math with them. It gives every empty square a value of one and every dark square a value of zero.
Next, it visits every row and counts how many empty squares are sitting side by side. If a row has three empty squares in a line, the computer updates those squares to say one, two, and three. This helps the computer remember how wide the empty space is at that exact spot.
Finally, the computer plays a game of looking for shapes. It picks a starting point and looks down through the rows. As it moves down, it checks how wide the empty space is, which it already calculated. It keeps going down as long as it finds empty squares, making the rectangle taller and taller while keeping track of its width. Every time it finds a new rectangle, it checks to see if it is bigger than the last one it found. It does this over and over until it has checked every possible rectangle on the entire sheet of paper.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||||
| www | AlgoMonster | C++ | Python | Java | TS | |||||
| WalkCCC | C++ | Python | Java | |||||||
| leetcode.ca | C++ | Python | C# | Rust | Java | Go | TS | |||
| LeetcodeHelp | C++ | Python | Java | |||||||
| MemoryLimitExceeded | C++ | Python | ||||||||
| Progiez | C++ | Python | Java | |||||||
| github | aylei | Rust | ||||||||
| begeekmyfriend | C | |||||||||
| BigEggStudy | C# | |||||||||
| black-shadows | C++ | |||||||||
| charles-wangkai | Java | |||||||||
| chenyanzhe | C++ | |||||||||
| everthis | JS | |||||||||
| FelixFan1122 | C# | |||||||||
| fengvyi | C++ | |||||||||
| fpdjsns | C++ | |||||||||
| gaosq0604 | Python | |||||||||
| Garvit244 | Python | |||||||||
| gouthampradhan | Java | |||||||||
| halfrost | Go | |||||||||
| haoel | C++ | |||||||||
| JoshCrozier | JS | |||||||||
| keineahnung2345 | C++ | |||||||||
| linouk23 | C++ | |||||||||
| lkwq007 | Python | |||||||||
| MacJim | C++ | |||||||||
| qiyuangong | Python | |||||||||
| ruoru | Rust | |||||||||
| shreymehul | C# | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| vli02 | C | |||||||||
| wisdompeak | C++ | |||||||||
| withaarzoo | C++ | |||||||||
| zfang399 | C++ | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C++, C#, Go, Java, Python, Rust, TypeScript | |||||||||
| LeetcodeHelp | C++, Java, Python | |||||||||
| MemoryLimitExceeded | Python, C++ | |||||||||
| Progiez | C++, Java, Python | |||||||||
| aylei | Rust | |||||||||
| begeekmyfriend | C | |||||||||
| BigEggStudy | C# | |||||||||
| black-shadows | C++, C++ | |||||||||
| charles-wangkai | Java | |||||||||
| chenyanzhe | C++ | |||||||||
| everthis | JavaScript | |||||||||
| FelixFan1122 | C# | |||||||||
| fengvyi | C++ | |||||||||
| fpdjsns | C++ | |||||||||
| gaosq0604 | Python | |||||||||
| Garvit244 | Python | |||||||||
| gouthampradhan | Java | |||||||||
| halfrost | Go | |||||||||
| haoel | C++ | |||||||||
| JoshCrozier | JavaScript | |||||||||
| keineahnung2345 | C++ | |||||||||
| linouk23 | C++ | |||||||||
| lkwq007 | Python | |||||||||
| MacJim | C++ | |||||||||
| qiyuangong | Python | |||||||||
| ruoru | Rust | |||||||||
| shreymehul | C# | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| vli02 | C | |||||||||
| wisdompeak | C++ | |||||||||
| withaarzoo | C++ | |||||||||
| zfang399 | C++ |
Videos
Similar Problems
- problem 84: Largest Rectangle in Histogram
- problem 221: Maximal Square
Solved On The Same Day
- problem 144: Binary Tree Preorder Traversal
- problem 145: Binary Tree Postorder Traversal
- problem 222: Count Complete Tree Nodes
- problem 404: Sum of Left Leaves
- problem 501: Find Mode in Binary Search Tree
- problem 543: Diameter of Binary Tree
- problem 559: Maximum Depth of N-ary Tree
- problem 589: N-ary Tree Preorder Traversal
- problem 590: N-ary Tree Postorder Traversal
- problem 637: Average of Levels in Binary Tree
- problem 700: Search in a Binary Search Tree
- problem 703: Kth Largest Element in a Stream
- problem 79: Word Search
- problem 81: Search in Rotated Sorted Array II
- problem 97: Interleaving String
- problem 99: Recover Binary Search Tree
- problem 173: Binary Search Tree Iterator
- problem 199: Binary Tree Right Side View
- problem 230: Kth Smallest Element in a BST
- problem 235: Lowest Common Ancestor of a Binary Search Tree
- problem 341: Flatten Nested List Iterator
- problem 429: N-ary Tree Level Order Traversal
- problem 508: Most Frequent Subtree Sum
- problem 513: Find Bottom Left Tree Value
- problem 538: Convert BST to Greater Tree
- problem 65: Valid Number
- problem 87: Scramble String
- problem 126: Word Ladder II
- problem 127: Word Ladder
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality