Given an m x n
2D binary grid grid
which represents a map of '1'
s (land) and '0'
s (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
Input: grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] Output: 1
Example 2:
Input: grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] Output: 3
Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
is '0'
or '1'
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine you have a map of land and water, and you want to find out how many separate islands there are. The brute force approach is like going over every single piece of land on the map to see if it's part of an island that you haven't already counted.
Here's how the algorithm would work step-by-step:
def number_of_islands_brute_force(grid):
if not grid:
return 0
number_of_rows = len(grid)
number_of_columns = len(grid[0])
number_of_islands = 0
visited = set()
def explore_island(row, column):
if (row < 0 or row >= number_of_rows or \
column < 0 or column >= number_of_columns or \
grid[row][column] == '0' or (row, column) in visited):
return
visited.add((row, column))
# Explore all 4 directions
explore_island(row + 1, column)
explore_island(row - 1, column)
explore_island(row, column + 1)
explore_island(row, column - 1)
for row in range(number_of_rows):
for column in range(number_of_columns):
# Start exploration if land is found
if grid[row][column] == '1' and (row, column) not in visited:
explore_island(row, column)
# Count a new island
number_of_islands += 1
return number_of_islands
The problem asks us to count separate landmasses on a map. The key idea is to treat the map like a graph and explore connected pieces of land, marking them as visited to avoid recounting them.
Here's how the algorithm would work step-by-step:
def number_of_islands(grid):
if not grid:
return 0
rows = len(grid)
cols = len(grid[0])
island_count = 0
def explore_island(row, col):
# Check boundaries and if the cell is land
if row < 0 or row >= rows or col < 0 or col >= cols or grid[row][col] == '0':
return
# Mark the current cell as visited by turning it into water
grid[row][col] = '0'
# Recursively explore adjacent land cells
explore_island(row + 1, col)
explore_island(row - 1, col)
explore_island(row, col + 1)
explore_island(row, col - 1)
for row in range(rows):
for col in range(cols):
if grid[row][col] == '1':
# Found a new island
island_count += 1
# Explore and mark the entire island
explore_island(row, col)
return island_count
Case | How to Handle |
---|---|
Null or empty grid input | Return 0 if the grid is null or has zero rows/columns, indicating no islands exist. |
Grid with only one cell | Check if the single cell is '1'; if so, return 1, otherwise return 0. |
Grid with all '0's (all water) | Return 0, as there are no islands. |
Grid with all '1's (one large island) | Return 1, as all land is connected. |
Grid with non-rectangular dimensions | Ensure the algorithm correctly handles rows of varying lengths or throws an error if non-rectangularity is not allowed. |
Integer overflow during recursion if the island is very large | Use iterative DFS or BFS to avoid potential stack overflow issues with very large islands and manage memory explicitly. |
Very large grid (performance considerations) | Employ an efficient algorithm like iterative Depth-First Search (DFS) or Breadth-First Search (BFS) with in-place modification (marking visited cells) to optimize space complexity. |
Grid contains characters other than '0' and '1' | Validate that only '0' and '1' characters are present, and either throw an error or treat other characters as water '0'. |