Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find all rectangles filled with 0 in Python
Finding all rectangles filled with 0s in a binary 2D matrix is a common problem in computer vision and image processing. We need to identify the starting and ending coordinates of each rectangular region containing only zeros.
The problem requires us to find rectangles that are separated (don't touch each other) but can touch array boundaries. Each rectangle is represented by four coordinates: [start_row, start_col, end_row, end_col].
Input Example
Consider this binary matrix where 1 represents filled cells and 0 represents empty cells ?
| 1 | 0 | 1 | 1 | 1 | 0 | 1 |
| 1 | 1 | 0 | 1 | 1 | 1 | 1 |
| 1 | 0 | 1 | 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 | 0 | 1 | 1 |
| 1 | 0 | 1 | 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 0 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 | 1 | 0 | 1 |
Algorithm Overview
The solution uses a flood-fill approach with the following steps ?
- Scan the matrix for unprocessed zeros (value 0)
- When found, start expanding the rectangle from that position
- Mark processed cells with value 5 to avoid revisiting
- Record the rectangle boundaries when expansion stops
Implementation
def find_rect(i, j, matrix, output, index):
"""Find rectangle boundaries starting from position (i,j)"""
rows = len(matrix)
cols = len(matrix[0])
flag_col = 0
flag_row = 0
# Expand rectangle row by row
for m in range(i, rows):
# Stop if we hit a 1 (filled cell)
if matrix[m][j] == 1:
flag_row = 1
break
# Skip if already processed
if matrix[m][j] == 5:
continue
# Expand this row column by column
for n in range(j, cols):
if matrix[m][n] == 1:
flag_col = 1
break
matrix[m][n] = 5 # Mark as processed
# Record rectangle boundaries
if flag_row == 1:
output[index].append(m - 1) # Last valid row
else:
output[index].append(m - 1) # Reached matrix boundary
if flag_col == 1:
output[index].append(n - 1) # Last valid column
else:
output[index].append(cols - 1) # Reached matrix boundary
def get_rectangles(matrix):
"""Main function to find all rectangles filled with zeros"""
rows = len(matrix)
rectangles = []
for i in range(rows):
for j in range(len(matrix[0])):
if matrix[i][j] == 0:
# Found start of new rectangle
rectangles.append([i, j]) # Add starting coordinates
find_rect(i, j, matrix, rectangles, len(rectangles) - 1)
return rectangles
# Test with the example matrix
test_matrix = [
[1, 0, 1, 1, 1, 0, 1],
[1, 1, 0, 1, 1, 1, 1],
[1, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1]
]
# Create a copy since the algorithm modifies the matrix
import copy
matrix_copy = copy.deepcopy(test_matrix)
result = get_rectangles(matrix_copy)
print("Rectangle coordinates [start_row, start_col, end_row, end_col]:")
for rect in result:
print(rect)
Rectangle coordinates [start_row, start_col, end_row, end_col]: [0, 1, 0, 1] [0, 5, 0, 5] [1, 2, 1, 2] [2, 1, 4, 1] [2, 4, 4, 4] [5, 1, 5, 1] [5, 3, 6, 6] [7, 1, 7, 1] [7, 5, 7, 5]
How the Algorithm Works
The algorithm processes the matrix systematically ?
- Detection: Scans left-to-right, top-to-bottom for zeros
- Expansion: From each zero, expands rightward and downward until hitting a 1 or boundary
- Marking: Marks processed cells with 5 to prevent duplicate processing
- Recording: Stores rectangle as [start_row, start_col, end_row, end_col]
Key Features
- Handles single-cell rectangles (like position [0,1] ? [0,1,0,1])
- Works with rectangles touching matrix boundaries
- Ensures rectangles don't overlap by marking processed cells
- Time complexity: O(rows × cols) since each cell is visited once
Conclusion
This flood-fill algorithm efficiently finds all rectangular regions of zeros in a binary matrix. It marks processed cells to avoid duplicates and returns coordinates for each rectangle found.
