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 the number of distinct islands in a 2D matrix in Python
An island in a 2D binary matrix is a group of connected land cells (represented by 1s) surrounded by water (represented by 0s). Islands are formed by connecting adjacent lands horizontally or vertically. We can solve this problem using Depth-First Search (DFS) to mark visited land cells.
Problem Visualization
Consider this binary matrix with three distinct islands ?
| 1 | 1 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 | 0 |
| 0 | 0 | 0 | 1 | 1 |
The blue cells form one island, green forms another, and red cells form the third island.
Algorithm Approach
The solution uses DFS to explore and mark all connected land cells as water once discovered:
- Iterate through each cell in the matrix
- When a land cell ('1') is found, increment the island counter
- Use DFS to mark all connected land cells as water ('0')
- Continue until all cells are processed
Implementation
class Solution:
def numIslands(self, grid):
"""
Count the number of islands in a 2D binary grid
:param grid: List[List[str]] - 2D grid of '0's and '1's
:return: int - number of islands
"""
if not grid or len(grid) == 0:
return 0
rows = len(grid)
cols = len(grid[0])
island_count = 0
for i in range(rows):
for j in range(cols):
if grid[i][j] == "1":
island_count += 1
self.dfs_mark_water(i, j, rows, cols, grid)
return island_count
def dfs_mark_water(self, i, j, rows, cols, grid):
"""
DFS to mark all connected land cells as water
"""
# Check boundaries
if i < 0 or j < 0 or i >= rows or j >= cols:
return
# If already water, return
if grid[i][j] == "0":
return
# Mark current cell as water
grid[i][j] = "0"
# Explore all 4 directions
self.dfs_mark_water(i + 1, j, rows, cols, grid) # Down
self.dfs_mark_water(i - 1, j, rows, cols, grid) # Up
self.dfs_mark_water(i, j + 1, rows, cols, grid) # Right
self.dfs_mark_water(i, j - 1, rows, cols, grid) # Left
# Test the solution
solution = Solution()
grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
result = solution.numIslands(grid)
print(f"Number of islands: {result}")
Number of islands: 3
How It Works
- Main Loop: Iterate through each cell in the grid
- Island Detection: When a '1' is found, increment the counter
- DFS Exploration: Mark all connected '1's as '0' to avoid counting them again
- Boundary Check: Ensure we don't go outside the grid boundaries
- Termination: DFS stops when it hits water ('0') or boundaries
Time and Space Complexity
| Aspect | Complexity | Explanation |
|---|---|---|
| Time | O(m × n) | Visit each cell once |
| Space | O(m × n) | DFS recursion stack in worst case |
Alternative Approach Using BFS
from collections import deque
class SolutionBFS:
def numIslands(self, grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
island_count = 0
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
for i in range(rows):
for j in range(cols):
if grid[i][j] == "1":
island_count += 1
# BFS to mark connected cells
queue = deque([(i, j)])
grid[i][j] = "0"
while queue:
r, c = queue.popleft()
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == "1":
grid[nr][nc] = "0"
queue.append((nr, nc))
return island_count
# Test BFS approach
solution_bfs = SolutionBFS()
grid2 = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
result2 = solution_bfs.numIslands(grid2)
print(f"Number of islands (BFS): {result2}")
Number of islands (BFS): 3
Conclusion
The island counting problem is efficiently solved using DFS or BFS to explore connected components. The DFS approach is simpler to implement with recursion, while BFS uses a queue for iterative exploration. Both methods achieve O(m × n) time complexity.
