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.