01 Matrix
The problem description can be found in LeetCode.
Approach
This is another example of an implicit Graph, as the Flood Fill problem we saw earlier.
The problem looks like a usual BFS one,
since it would be enough to search at the nearest 0
if the cell is not equal to 0
.
However, if we imagine an input like:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 0
We would need to make a BFS
times,
which is .
A smarter way would be to build the result matrix from scratch.
We can initialize our queue with only coordinates of 0
values.
Then, we can perform a BFS
algorithm to update the distances of the cells that are not equal to 0
.
Solution
from collections import deque
from typing import Deque, Iterator, List, Set, Tuple
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
# not ideal, but just to avoid to have too many function parameters
self.mat = mat
self.rows, self.cols = len(mat), len(mat[0])
visited = set()
queue: Deque[Tuple[int, int]] = deque()
for row in range(self.rows):
for col in range(self.cols):
if self.mat[row][col] == 0:
visited.add((row, col))
queue.append((row, col))
self.bfs(row, col, queue, visited)
return self.mat
def bfs(
self,
row: int,
col: int,
queue: Deque[Tuple[int, int]],
visited: Set[Tuple[int, int]],
) -> None:
distance = 0
while queue:
for _ in range(len(queue)):
row, col = queue.popleft()
self.mat[row][col] = distance
for nbr_row, nbr_col in self.get_neighbors(row, col):
if (nbr_row, nbr_col) in visited:
continue
visited.add((nbr_row, nbr_col))
queue.append((nbr_row, nbr_col))
distance += 1
def get_neighbors(self, row: int, col: int) -> Iterator[Tuple[int, int]]:
deltas = [
(-1, 0), # up
(+1, 0), # down
(0, -1), # left
(0, +1), # right
]
for dt_row, dt_col in deltas:
nbr_row = row + dt_row
nbr_col = col + dt_col
if (
0 <= nbr_row < self.rows
and 0 <= nbr_col < self.cols
and self.mat[nbr_row][nbr_col] != 0
):
yield nbr_row, nbr_col
Complexity
- Time:
- Space:
Where and are the number of rows and columns of the input matrix, respectively.