Problem
Given a binary matrix of size N × M
(0/1 entries), find the largest plus-shaped cross composed entirely of 1
s. A cross has a center cell and four arms (up/down/left/right) of equal length k
(number of cells from the center to the arm end). The goal is to return the center coordinates and the arm length k
of the largest cross. When the matrix is sparse (only P
ones, where P << N*M
), prefer memory-efficient approaches.
Example (center at row=2, col=2 with arm length = 1):
|
|
Solution
We present two common approaches:
- Method 1 — DP over the full grid (O(NM) time and O(NM) space): compute, for every cell, the number of consecutive ones in the four directions and take the maximum of the minima.
- Method 2 — Sparse-optimized graph approach (O(P) time and memory): store only the coordinates of ones, link neighbors, and compute line lengths by traversing adjacency lists with memoization.
Method 1 — Dynamic Programming (full-grid)
Intuition
For each cell (i,j)
compute up[i][j]
, down[i][j]
, left[i][j]
, right[i][j]
— the lengths of consecutive ones including the cell itself in each direction. The largest arm length centered at (i,j)
is min(up, down, left, right) - 1
(subtract 1 to exclude the center if you want arm length). The answer is the maximum over all cells.
Approach
- Initialize four
N×M
arraysup/down/left/right
with zeros. - Fill
up
andleft
in a top-left to bottom-right pass: ifmat[i][j] == 1
thenup[i][j] = 1 + up[i-1][j]
andleft[i][j] = 1 + left[i][j-1]
else 0. - Fill
down
andright
in a bottom-right to top-left pass similarly. - For every cell with value
1
, computearm = min(up, down, left, right) - 1
; track the maximumarm
and the center.
Edge cases: empty matrix, all zeros.
Code
|
|
|
|
|
|
|
|
Complexity
- ⏰ Time complexity:
O(N*M)
— we perform a constant amount of work per cell in the two passes and a final scan. - 🧺 Space complexity:
O(N*M)
for four direction arrays (can be reduced toO(M)
by streaming rows if needed).
Method 2 — Sparse-optimized graph approach
Intuition
When only P
cells contain 1
, building full N×M
arrays is wasteful. Store the coordinates of 1
s in a hash set and build an adjacency-like structure that links each cell to its immediate neighbor in four directions (if present). Then compute line lengths along each direction using memoization and iterative stack to avoid recursion. The algorithm visits each occupied cell a constant number of times; overall time and memory are O(P)
.
Approach
- Represent each occupied cell
(r,c)
as a packed key (e.g.,(r<<32) | c
) and insert into a map from key to Vertex structure. - For every Vertex, set pointers to its up/down/left/right neighbours by looking up keys
toKey(r-1,c)
etc. - For each Vertex and each direction, compute the contiguous line length by walking along the neighbor chain until a cached length or end is reached; use a stack to fill memoized lengths iteratively (avoid recursion).
- For each Vertex that has all four neighbours (a potential center) compute
arm = min(topLen, bottomLen, leftLen, rightLen) - 1
and track the best.
This is the method implemented in the original article; below are compact implementations in Java and Python, adapted from the article. The Java version follows the Vertex/Sibling pattern; the Python version uses dictionaries and iterative memoization.
Code (Java)
|
|
Code (Python)
|
|
Complexity
- ⏰ Time complexity:
O(P)
— each occupied cell and each direction is visited a constant number of times thanks to memoization. - 🧺 Space complexity:
O(P)
for maps and memo caches.
Notes
- This problem is equivalent to the LeetCode problem “Largest Plus Sign” (see
related_problems
). The DP method is simpler to implement whenN*M
is small; the sparse-optimized method is preferable for large grids with few ones. - I preserved the original reference and gist links in
source_links
above. Created at: 2018-09-08T08:58:51+02:00 Updated at: 2018-09-08T08:58:51+02:00