Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.