Before attempting this problem, you should be comfortable with:
For each empty land cell, we want to know the sum of distances to all houses. BFS from each empty cell finds the shortest path to each house. If an empty cell cannot reach all houses, we mark it as blocked to avoid checking it again in future iterations.
This approach works well when there are many houses but few empty cells.
0):BFS to find distances to all reachable houses.2) to prune future searches.-1 if no valid cell exists.class Solution:
def shortestDistance(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0])
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
total_houses = 0
for row in range(rows):
for col in range(cols):
if grid[row][col] == 1:
total_houses += 1
def bfs(start_row, start_col):
distance_sum = 0
houses_reached = 0
q = deque([(start_row, start_col)])
vis = [[False] * cols for _ in range(rows)]
vis[start_row][start_col] = True
steps = 0
while q and houses_reached != total_houses:
for _ in range(len(q)):
row, col = q.popleft()
if grid[row][col] == 1:
distance_sum += steps
houses_reached += 1
continue
for dr, dc in dirs:
next_row, next_col = row + dr, col + dc
if 0 <= next_row < rows and 0 <= next_col < cols:
if not vis[next_row][next_col] and grid[next_row][next_col] != 2:
vis[next_row][next_col] = True
q.append((next_row, next_col))
steps += 1
if houses_reached != total_houses:
for row in range(rows):
for col in range(cols):
if grid[row][col] == 0 and vis[row][col]:
grid[row][col] = 2
return float('inf')
return distance_sum
min_distance = float('inf')
for row in range(rows):
for col in range(cols):
if grid[row][col] == 0:
min_distance = min(min_distance, bfs(row, col))
return -1 if min_distance == float('inf') else min_distanceWhere and are the number of rows and columns in
gridrespectively.
Instead of searching from empty cells, we search from each house. Each BFS computes the distance from one house to all reachable empty cells. We accumulate these distances in a separate matrix.
For each empty cell, we also track how many houses can reach it. Only cells reachable by all houses are valid candidates.
distances matrix where each cell stores [total_distance, house_count].1):BFS to all reachable empty cells.house_count == total_houses.-1 if no valid cell exists.class Solution:
def shortestDistance(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0])
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
total_houses = 0
distances = [[[0, 0] for _ in range(cols)] for _ in range(rows)]
def bfs(start_row, start_col):
q = deque([(start_row, start_col)])
vis = [[False] * cols for _ in range(rows)]
vis[start_row][start_col] = True
steps = 0
while q:
for _ in range(len(q)):
row, col = q.popleft()
if grid[row][col] == 0:
distances[row][col][0] += steps
distances[row][col][1] += 1
for dr, dc in dirs:
next_row, next_col = row + dr, col + dc
if 0 <= next_row < rows and 0 <= next_col < cols:
if not vis[next_row][next_col] and grid[next_row][next_col] == 0:
vis[next_row][next_col] = True
q.append((next_row, next_col))
steps += 1
for row in range(rows):
for col in range(cols):
if grid[row][col] == 1:
total_houses += 1
bfs(row, col)
min_distance = float('inf')
for row in range(rows):
for col in range(cols):
if distances[row][col][1] == total_houses:
min_distance = min(min_distance, distances[row][col][0])
return -1 if min_distance == float('inf') else min_distanceWhere and are the number of rows and columns in
gridrespectively.
We can optimize the previous approach by eliminating the separate visited array and the house count tracking. The key insight is to use the grid values themselves as visit markers.
Initially, empty cells have value 0. After the first house's BFS, all reachable empty cells are decremented to -1. The second house's BFS only visits cells with value -1 (reachable by exactly one house), and decrements them to -2. This continues for each house. Cells that become unreachable are naturally pruned.
total matrix to accumulate distances.emptyLandValue = 0.BFS, only visiting cells with value equal to emptyLandValue.total and decrement the cell value.BFS.emptyLandValue for the next iteration.-1 if no valid cell exists.class Solution:
def shortestDistance(self, grid: List[List[int]]) -> int:
# Next four directions.
dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]]
rows = len(grid)
cols = len(grid[0])
# Total Matrix to store total distance sum for each empty cell.
total = [[0] * cols for _ in range(rows)]
empty_land_value = 0
min_dist = float('inf')
for row in range(rows):
for col in range(cols):
# Start a BFS from each house.
if grid[row][col] == 1:
min_dist = float('inf')
# Use a queue to perform a BFS, starting from the cell at (row, col).
q = deque([(row, col)])
steps = 0
while q:
steps += 1
level_size = len(q)
for level in range(level_size):
curr = q.popleft()
for dir in dirs:
next_row = curr[0] + dir[0]
next_col = curr[1] + dir[1]
# For each cell with the value equal to empty land value
# add distance and decrement the cell value by 1.
if (0 <= next_row < rows and
0 <= next_col < cols and
grid[next_row][next_col] == empty_land_value):
grid[next_row][next_col] -= 1
total[next_row][next_col] += steps
q.append((next_row, next_col))
min_dist = min(min_dist, total[next_row][next_col])
# Decrement empty land value to be searched in next iteration.
empty_land_value -= 1
return -1 if min_dist == float('inf') else min_distWhere and are the number of rows and columns in
gridrespectively.
An empty cell is only valid if it can reach ALL houses. Simply finding the minimum distance sum is insufficient; you must also verify that the cell can reach every house. Cells that cannot reach all houses should be excluded from consideration, or the solution returns -1 if no valid cell exists.
Some implementations try to optimize by stopping BFS early when a house is found. However, BFS from a house must continue to all reachable empty cells to correctly accumulate distances. Early termination leads to incomplete distance sums and incorrect results.
The optimized approach uses decreasing values (0, -1, -2, ...) to track which cells are reachable by all previously processed houses. A common mistake is not understanding that a cell with value k should only be visited by the (|k|+1)-th house's BFS. Cells not matching the expected value are either obstacles, houses, or unreachable from some previous house.
There are two valid approaches: BFS from empty cells to houses, or BFS from houses to empty cells. Mixing concepts from both approaches leads to incorrect logic. When doing BFS from houses, each house's BFS contributes distances to empty cells. When doing BFS from empty cells, each empty cell computes its total distance to all houses.
In large grids with many houses, the sum of distances can become very large. Using Integer.MAX_VALUE or similar sentinels for invalid cells, then performing arithmetic operations, can cause overflow. Ensure proper handling of sentinel values in comparisons and avoid adding to them.