Given an m x n
binary matrix grid
, an island is a group of 1
's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
An island is considered to be the same as another if and only if one island can be translated (without rotation or reflection) to equal the other.
Return the number of distinct islands.
Example 1:
Input: grid = [ [1,1,0,0,0], [1,1,0,0,0], [0,0,0,1,1], [0,0,0,1,1] ] Output: 1
Example 2:
Input: grid = [ [1,1,0,1,1], [1,0,0,0,0], [0,0,0,1,1], [1,1,0,1,0] ] Output: 3
Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 50
grid[i][j]
is either 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:
We want to find the number of different island shapes in a grid. The brute force way is to explore each piece of land on the grid, recording the shape of the island it belongs to, and then comparing all the island shapes to see how many are truly distinct.
Here's how the algorithm would work step-by-step:
def number_of_distinct_islands(grid):
number_of_rows = len(grid)
number_of_columns = len(grid[0])
island_shapes = set()
def explore_island(row, column, path, start_row, start_column):
if row < 0 or row >= number_of_rows or column < 0 or column >= number_of_columns or grid[row][column] == 0:
return
grid[row][column] = 0
# Record the path relative to the starting point
path.append((row - start_row, column - start_column))
explore_island(row + 1, column, path, start_row, start_column)
explore_island(row - 1, column, path, start_row, start_column)
explore_island(row, column + 1, path, start_row, start_column)
explore_island(row, column - 1, path, start_row, start_column)
for row in range(number_of_rows):
for column in range(number_of_columns):
if grid[row][column] == 1:
island_path = []
# We need to capture the shape of this specific island.
explore_island(row, column, island_path, row, column)
island_shapes.add(tuple(island_path))
return len(island_shapes)
The goal is to identify unique island shapes within a grid. We can find all connected land pieces and represent the shape of each island as a unique string representing movements to explore it. We use this string as a way of 'fingerprinting' the island, and count how many unique fingerprints we find.
Here's how the algorithm would work step-by-step:
def number_of_distinct_islands(grid):
if not grid:
return 0
number_of_rows = len(grid)
number_of_columns = len(grid[0])
distinct_islands = set()
def explore_island(row, column, path):
if row < 0 or row >= number_of_rows or column < 0 or column >= number_of_columns or grid[row][column] == 0:
return
grid[row][column] = 0 # Mark as visited to avoid cycles.
path.append('D')
explore_island(row + 1, column, path)
path.append('U')
explore_island(row - 1, column, path)
path.append('R')
explore_island(row, column + 1, path)
path.append('L')
explore_island(row, column - 1, path)
path.append('B') #Backtrack
for row in range(number_of_rows):
for column in range(number_of_columns):
if grid[row][column] == 1:
# Found a new island, explore it.
island_path = []
explore_island(row, column, island_path)
# Generate a unique fingerprint for the island.
island_string = ''.join(island_path)
#Only add the island if it is unique
if island_string not in distinct_islands:
distinct_islands.add(island_string)
#The total count of the distinct islands are returned
return len(distinct_islands)
Case | How to Handle |
---|---|
Null or empty grid | Return 0 as there are no islands in an empty grid |
Grid with all water (all 0s) | Return 0 as there are no islands to count |
Grid with all land (all 1s) | Return 1 if all cells are connected forming only one island shape |
Grid with a single '1' surrounded by '0's | The algorithm correctly identifies this as a single island |
Large grid size, potential stack overflow with recursion | Use iterative DFS (using a stack data structure) instead of recursive DFS to prevent stack overflow errors |
Grid containing disconnected islands with identical shapes | The shape comparison logic will correctly identify these as duplicates. |
Grid with islands touching at corners only (not considered connected) | Ensure the DFS only considers adjacent (up, down, left, right) cells, not diagonal ones. |
Integer overflow in grid dimensions (rows * cols) | Check dimensions for reasonableness to avoid potential integer overflow when used in calculations |