You are given an n x n
binary matrix grid
. You are allowed to change at most one 0
to be 1
.
Return the size of the largest island in grid
after applying this operation.
An island is a 4-directionally connected group of 1
s.
Example 1:
Input: grid = [[1,0],[0,1]] Output: 3 Explanation: Change one 0 to 1 and connect two 1s, then we get an island with area = 3.
Example 2:
Input: grid = [[1,1],[1,0]] Output: 4 Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4.
Example 3:
Input: grid = [[1,1],[1,1]] Output: 4 Explanation: Can't change any 0 to 1, only one island with area = 4.
Constraints:
n == grid.length
n == grid[i].length
1 <= n <= 500
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:
The problem asks to find the largest island you can make by changing one zero to a one in a grid of zeros and ones. The brute force approach tries flipping every single zero to a one, and then calculates the size of the island that results from each flip.
Here's how the algorithm would work step-by-step:
def making_a_large_island_brute_force(grid):
max_island_size = 0
grid_row_length = len(grid)
grid_column_length = len(grid[0])
def calculate_island_size(row, column, current_grid, visited):
if row < 0 or row >= grid_row_length or column < 0 or column >= grid_column_length or \
(row, column) in visited or current_grid[row][column] == 0:
return 0
visited.add((row, column))
size = 1
size += calculate_island_size(row + 1, column, current_grid, visited)
size += calculate_island_size(row - 1, column, current_grid, visited)
size += calculate_island_size(row, column + 1, current_grid, visited)
size += calculate_island_size(row, column - 1, current_grid, visited)
return size
for row_index in range(grid_row_length):
for column_index in range(grid_column_length):
if grid[row_index][column_index] == 0:
# Temporarily flip the zero to a one
grid[row_index][column_index] = 1
# Calculate the island size after the flip
island_size = calculate_island_size(row_index, column_index, grid, set())
# Update the max size if needed
max_island_size = max(max_island_size, island_size)
# Flip it back
grid[row_index][column_index] = 0
# If the grid only contained zeroes, return 1
if max_island_size == 0:
all_ones = True
for row_index in range(grid_row_length):
for column_index in range(grid_column_length):
if grid[row_index][column_index] == 0:
all_ones = False
break
if not all_ones:
break
if all_ones and grid_row_length > 0:
return grid_row_length * grid_column_length
else:
return 1
# Check if all cells are already 1s
all_ones = True
for row_index in range(grid_row_length):
for column_index in range(grid_column_length):
if grid[row_index][column_index] == 0:
all_ones = False
break
if not all_ones:
break
if all_ones:
# Grid is all ones, return its area
return grid_row_length * grid_column_length
return max_island_size
The goal is to find the largest connected area of land ('1's) you can create by changing a single patch of water ('0') to land. The optimal approach avoids re-calculating the size of connected land areas by pre-calculating and storing these sizes, then efficiently checking the neighbors of each water patch.
Here's how the algorithm would work step-by-step:
def making_a_large_island(grid):
rows = len(grid)
cols = len(grid[0])
land_size_by_label = {}
label = 2
def get_land_size(row, col, current_label):
if row < 0 or row >= rows or col < 0 or col >= cols or grid[row][col] != 1:
return 0
grid[row][col] = current_label
return 1 + get_land_size(row + 1, col, current_label) + \
get_land_size(row - 1, col, current_label) + \
get_land_size(row, col + 1, current_label) + \
get_land_size(row, col - 1, current_label)
# Assign a unique label to each land area and record its size
for row in range(rows):
for col in range(cols):
if grid[row][col] == 1:
land_size = get_land_size(row, col, label)
land_size_by_label[label] = land_size
label += 1
largest_island_size = 0
# Iterate through water patches and check the neighboring land areas
for row in range(rows):
for col in range(cols):
if grid[row][col] == 0:
neighboring_labels = set()
size = 1 # Start with 1 for the water patch itself
# Check the 4 neighbors (up, down, left, right)
for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
new_row, new_col = row + dr, col + dc
if 0 <= new_row < rows and 0 <= new_col < cols and grid[new_row][new_col] != 0:
neighbor_label = grid[new_row][new_col]
# Only add the land size if the label hasn't been seen yet
if neighbor_label not in neighboring_labels:
size += land_size_by_label[neighbor_label]
neighboring_labels.add(neighbor_label)
largest_island_size = max(largest_island_size, size)
# If no '0' was found, the whole grid was a single island
if largest_island_size == 0:
return rows * cols
return largest_island_size
Case | How to Handle |
---|---|
Null or empty grid | Return 0, as no island exists in an empty grid. |
Grid with all 0s (no islands) | Return 0, because no island exists to potentially expand. |
Grid with all 1s (one large island) | Return rows * cols, as flipping a 0 won't increase island size. |
Grid with only one row or one column | The algorithm should still correctly identify and calculate the connected components and handle the boundary conditions for flipping a '0' to a '1'. |
Grid dimensions are at maximum constraints | Ensure the solution uses appropriate data structures and algorithms (e.g., DFS/BFS with efficient memory management) to avoid exceeding memory limits. |
Integer overflow when calculating island size | Use a data type that can accommodate large island sizes (e.g., long) for calculating the island size. |
Multiple possible '0' flips resulting in the same maximum island size. | The solution should return the maximum possible size, regardless of how many locations result in that maximum. |
Disjoint islands separated by multiple 0s | The algorithm must correctly consider neighboring islands separated by multiple 0s and identify the largest combined size after flipping one 0. |