{x}
blog image

The Maze III

Solution Explanation for LeetCode 499: The Maze III

This problem requires finding the lexicographically smallest shortest path from a starting point (ball) to an ending point (hole) in a maze, where the ball continues rolling in a direction until it hits a wall. We'll use a Breadth-First Search (BFS) approach to find the shortest path and handle lexicographical ordering.

Approach

  1. Data Structures:

    • A queue (q) to manage the BFS traversal. Each element in the queue will represent a position (row, column) in the maze.
    • A 2D array dist to store the shortest distance from the starting point to each cell. We'll initialize it with infinity for all cells except the starting point, which will be 0.
    • A 2D array path to store the shortest path (string of directions) to each cell.
    • dirs: A list of directions (up, down, left, right) with their corresponding row/column offsets and character representation.
  2. BFS Traversal:

    • Start by adding the ball's position to the queue q.
    • While the queue is not empty:
      • Dequeue a cell (row, col) from the queue.
      • For each direction in dirs:
        • Simulate the ball rolling in that direction until it hits a wall or the hole. Calculate the distance step during this roll.
        • If the calculated distance step is shorter than the current shortest distance to the cell where the ball stopped (dist[x][y]), or if the distance is the same but the new path is lexicographically smaller, update dist[x][y] and path[x][y].
        • If the ball didn't reach the hole, add the new position to the queue.
  3. Result:

    • After the BFS completes, path[rh][ch] (where rh and ch are the hole's coordinates) will contain the lexicographically smallest shortest path to the hole. If it's an empty string, it means the hole is unreachable, and we return "impossible".

Time and Space Complexity Analysis

  • Time Complexity: O(M * N), where M and N are the dimensions of the maze. In the worst-case scenario, we visit each cell in the maze. The rolling simulation in each direction takes, at most, O(M + N) time, but it's amortized over the entire search, resulting in the O(M * N) complexity.

  • Space Complexity: O(M * N) to store the dist and path arrays. The queue's size is also at most O(M * N) in the worst case.

Code (Python)

from collections import deque
import math
 
class Solution:
    def findShortestWay(self, maze: List[List[int]], ball: List[int], hole: List[int]) -> str:
        m, n = len(maze), len(maze[0])
        r, c = ball
        rh, ch = hole
        q = deque([(r, c)])
        dist = [[math.inf] * n for _ in range(m)]
        dist[r][c] = 0
        path = [[""] * n for _ in range(m)]
        dirs = [(-1, 0, 'u'), (1, 0, 'd'), (0, -1, 'l'), (0, 1, 'r')]
 
        while q:
            i, j = q.popleft()
            for a, b, d in dirs:
                x, y, step = i, j, dist[i][j]
                while 0 <= x + a < m and 0 <= y + b < n and maze[x + a][y + b] == 0 and (x != rh or y != ch):
                    x += a
                    y += b
                    step += 1
                if dist[x][y] > step or (dist[x][y] == step and path[i][j] + d < path[x][y]):
                    dist[x][y] = step
                    path[x][y] = path[i][j] + d
                    if (x, y) != (rh, ch):
                        q.append((x, y))
 
        return path[rh][ch] if path[rh][ch] else "impossible"
 

The code in other languages (Java, C++, Go) follows a similar structure, adapting the syntax and data structures specific to each language. The core logic of BFS, distance tracking, and lexicographical path comparison remains consistent across all implementations.