LC286. Walls and Gates¶
Problem Description¶
LeetCode Problem 286: You are given an m x n
grid rooms
initialized with these three possible values.
-1
A wall or an obstacle.0
A gate.INF
Infinity means an empty room. We use the value231 - 1 = 2147483647
to representINF
as you may assume that the distance to a gate is less than2147483647
.
Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF
.
Clarification¶
- There are multiple gates. Room value is the steps to the nearest gate.
Assumption¶
- If the room can be reached, steps to the gate <
Inf
Solution¶
Approach - BFS 1 Gate¶
Find gate one at a time and use breadth-first search to search all rooms the gate can reach and update room value if is smaller.
Note that no need to store visited rooms since room value reflects whether it is visited. Another trick is to update the room value based on last room and no need to stop step value.
class Solution:
def wallsAndGates(self, rooms: List[List[int]]) -> None:
"""
Do not return anything, modify rooms in-place instead.
"""
queue = deque()
n_row = len(rooms)
n_col = len(rooms[0])
for i_row in range(n_row):
for j_col in range(n_col):
if rooms[i_row][j_col] == 0:
queue.append((i_row, j_col))
# Use BFS to travers roomsa and update the room value
# for the gate
while queue:
size = len(queue)
for i in range(size):
base_row, base_col = queue.popleft()
for row_step, col_step in [(-1, 0), (0, 1), (0, -1), (1, 0)]:
curr_row = base_row + row_step
curr_col = base_col + col_step
if curr_row >= 0 and curr_row < n_row \
and curr_col >= 0 and curr_col < n_col \
and rooms[curr_row][curr_col] > rooms[base_row][base_col] + 1:
rooms[curr_row][curr_col] = rooms[base_row][base_col] + 1
queue.append((curr_row, curr_col))
Complexity Analysis¶
- Time complexity: \(O(kmn)\)
If there is ONLY one gate, the breadth-first search takes at most m×n steps to reach all rooms, therefore the time complexity is \(O(mn)\). When there arek
gates, on average the space will be essentially divided byk
subspaces since each BFS will only search rooms with larger value. So the time complexity is \(O(\frac{k}{k}mn) + O(\frac{k-1}{k}mn) + \cdots + O(\frac{1}{k}mn) = O(\frac{1+k}{2} mn)\). So in worth case, the time complexity is \(O(kmn)\). - Space complexity: \(O(mn)\)
The space complexity depends on the queue's size. We insert at most \(m \times n\) points into the queue.
Approach - BFS All Gates¶
Add all gates to the queue first and then check the same layer of each node and add empty rooms to the queue. Essentially, always check the same layer of all gates, when checking 1st layer, if room is empty, update with 1
and add it to the queue. When checking kth
layer, if the room is empty, update the room with value k
and add it to the queue. For kth
layer, if room is updated for one gate with k
, no need to update it for another gate since it will be update by the same value.
from collections import deque
class Solution:
EMPTY = 2**31 - 1
GATE = 0
DIRECTIONS = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def wallsAndGates(self, rooms: List[List[int]]) -> None:
"""
Do not return anything, modify rooms in-place instead.
"""
n_row = len(rooms)
if n_row == 0:
return
n_col = len(rooms[0])
queue = deque()
for i_row in range(n_row):
for i_col in range(n_col):
if rooms[i_row][i_col] == self.GATE:
queue.append((i_row, i_col))
while queue:
current_row, current_col = queue.popleft()
for step_row, step_col in self.DIRECTIONS:
next_row = current_row + step_row
next_col = current_col + step_col
if next_row >= 0 and next_row < n_row \
and next_col >= 0 and next_col < n_col \
and rooms[next_row][next_col] == self.EMPTY:
rooms[next_row][next_col] = rooms[current_row][current_col] + 1
queue.append((next_row, next_col))
Complexity Analysis¶
- Time complexity: \(O(mn)\)
Since it is only check non-empty rooms once, so in worth case, the time complexity is \(O(mn)\). - Space complexity: \(O(mn)\)
The space complexity depends on the queue's size. We insert at most \(m \times n\) points into the queue.
Comparison of Different Approaches¶
The table below summarize the time complexity and space complexity of different approaches:
Approach | Time Complexity | Space Complexity |
---|---|---|
Approach - BFS 1 gate | \(O(kmn)\) | \(O(mn)\) |
Approach - BFS all gates | \(O(mn)\) | \(O(mn)\) |