{x}
blog image

Walls and Gates

Solution Explanation for Walls and Gates

This problem involves finding the shortest distance from each empty room to the nearest gate in a grid. The grid contains walls (-1), gates (0), and empty rooms (represented by INF, a large integer). The solution uses Breadth-First Search (BFS) to efficiently determine these distances.

Approach:

  1. Initialization: We begin by identifying all gate cells (cells with value 0). These cells are added to a queue (q) for BFS processing. We also initialize a distance variable d to 0.

  2. BFS Traversal: The core of the algorithm is a BFS traversal. In each iteration of the while loop (while q):

    • We increment d (distance from the gates).
    • We process all cells currently in the queue. The number of cells to be processed is stored in len(q) (or similar in other languages) to ensure that we're only working with cells added in the previous iteration. This is crucial for maintaining the level-order traversal that BFS guarantees.
    • For each cell (i, j) in the queue, we explore its four neighbors (up, down, left, right) using a for loop and direction array.
    • If a neighbor cell is an empty room (rooms[x][y] == INF), we update its distance to the current distance d (rooms[x][y] = d) and add it to the queue for processing in the next iteration.
  3. In-place Modification: The solution directly modifies the input rooms array. This is specified by the problem statement.

Time and Space Complexity Analysis:

  • Time Complexity: O(M * N), where M and N are the dimensions of the grid. Each cell in the grid is visited and processed at most once during the BFS.

  • Space Complexity: O(M * N) in the worst case. This is because the queue could potentially hold all the cells in the grid if there are no walls or obstacles. In practice, the space used will likely be less than O(M*N) because it's usually less likely all cells are empty rooms that need to be updated.

Code Examples (with explanations):

The provided code in Python, Java, C++, and Go all implement the same BFS algorithm. Let's break down the Python code as an example:

class Solution:
    def wallsAndGates(self, rooms: List[List[int]]) -> None:
        m, n = len(rooms), len(rooms[0])
        inf = 2**31 - 1
        q = deque([(i, j) for i in range(m) for j in range(n) if rooms[i][j] == 0]) #Queue initialization - all gates are added.
        d = 0
        while q:
            d += 1
            for _ in range(len(q)): #Process all cells added in previous iteration
                i, j = q.popleft()
                for a, b in [[0, 1], [0, -1], [1, 0], [-1, 0]]: #directions (right,left,down,up)
                    x, y = i + a, j + b
                    if 0 <= x < m and 0 <= y < n and rooms[x][y] == inf: #check bounds & empty room
                        rooms[x][y] = d #update distance
                        q.append((x, y)) #add to the queue

The other language versions follow the same logic, differing mainly in syntax and data structure implementations (using LinkedList in Java, queue in C++, and slices in Go for the queue). The dirs array (or its equivalent) efficiently handles the exploration of neighboring cells. The use of deque in Python, and similar queue structures in other languages, optimizes the queue operations for fast enqueue and dequeue.