529. Minesweeper - Detailed Explanation
Problem Statement
Description:
You are given a 2D board representing a Minesweeper game. Each cell on the board can be one of the following characters:
'M'
– an unrevealed mine,'E'
– an unrevealed empty square,'B'
– a revealed blank square with no adjacent mines,'1'
to'8'
– a revealed square indicating the number of adjacent mines,'X'
– a revealed mine (game over).
You are also given a click position (a pair of row and column indices). Based on the click, update the board as follows:
- Mine Clicked:
If a mine ('M'
) is clicked, change it to'X'
to mark that the game is over. - Empty Square Clicked (No Adjacent Mines):
If an empty square ('E'
) with no adjacent mines is revealed, change it to a blank ('B'
). Then, recursively reveal all of its adjacent unrevealed squares. - Empty Square Clicked (With Adjacent Mines):
If an empty square ('E'
) with one or more adjacent mines is revealed, change it to a digit ('1'
to'8'
) representing the number of adjacent mines. - Stop Condition:
Return the updated board when no more squares can be revealed.
Examples:
-
Example 1:
Input:
board = [['E', 'E', 'E', 'E', 'E'], ['E', 'E', 'M', 'E', 'E'], ['E', 'E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E', 'E']] click = [3, 0]
Output:
[['B', '1', 'E', '1', 'B'], ['B', '1', 'M', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']]
Explanation:
The click at position[3, 0]
(bottom-left corner) reveals an empty square with no adjacent mines. A recursive reveal then occurs to all adjacent squares. For squares adjacent to a mine, the count is shown. -
Example 2:
Input:
board = [['B', '1', 'E', '1', 'B'], ['B', '1', 'M', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']] click = [1, 2]
Output:
[['B', '1', 'E', '1', 'B'], ['B', '1', 'X', '1', 'B'], ['B', '1', '1', '1', 'B'], ['B', 'B', 'B', 'B', 'B']]
Explanation:
The click at position[1, 2]
hits a mine. The mine is then revealed as'X'
, indicating game over.
Constraints:
- The board is a 2D array of characters.
- The click is a valid coordinate within the board.
- Board dimensions and the number of mines/empty squares vary, but you can assume the board is not empty.
Hints Before Diving into the Solution
-
Hint 1:
Think about how you can explore the board in all 8 directions (up, down, left, right, and the 4 diagonals) from any given cell. This is crucial for counting adjacent mines and for the recursive reveal. -
Hint 2:
When revealing cells, consider using either Depth-First Search (DFS) or Breadth-First Search (BFS). What conditions will determine whether you should stop the search in a certain direction?
Approach 1: Depth-First Search (DFS)
Idea:
-
Click a Mine:
If the clicked cell is'M'
, update it to'X'
and return immediately. -
Reveal an Empty Cell:
If the clicked cell is'E'
, count the number of adjacent mines by exploring all 8 directions.- No Adjacent Mines:
If the count is zero, change the cell to'B'
and recursively reveal all adjacent unrevealed cells. - Adjacent Mines Present:
If the count is greater than zero, update the cell with the count (as a character) and stop further exploration from that cell.
- No Adjacent Mines:
Visual Walkthrough:
Imagine a cell at position (i, j)
. For each of the 8 directions (e.g., (i-1, j)
, (i+1, j)
, (i, j-1)
, (i, j+1)
, and the four diagonals), check if the cell contains a mine ('M'
).
- If zero mines are adjacent, mark it as
'B'
and perform DFS on its neighbors. - If there are mines present, update the cell with the number of mines and do not explore its neighbors.
Approach 2: Breadth-First Search (BFS)
Idea:
- Use a Queue:
Start by adding the clicked cell to a queue. - Process Each Cell:
While the queue is not empty:- Remove a cell from the queue.
- If it is an empty cell (
'E'
), count adjacent mines. - If the count is zero, mark the cell as
'B'
and enqueue all adjacent unrevealed cells. - Otherwise, update the cell with the count.
- Stop When Done:
Continue until there are no cells left to process in the queue.
Comparison:
- DFS is naturally recursive and might be easier to implement, but it could run into deep recursion issues on large boards.
- BFS uses an iterative approach with a queue, which can help avoid recursion depth problems and might be preferred when the board is large.
Python Code
Java Code
Complexity Analysis
-
Time Complexity:
In the worst-case scenario, you might end up visiting every cell once. Hence, the time complexity is O(m * n), where m is the number of rows and n is the number of columns. -
Space Complexity:
- For DFS, the recursion stack may go as deep as O(m * n) in the worst case.
- For BFS (if implemented), you’d use additional space for the queue but it would also be O(m * n).
- The board itself is modified in place, so extra space is minimal beyond recursion/queue.
Step-by-Step Walkthrough & Visual Example
Consider Example 1:
board = [['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'M', 'E', 'E'],
['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'E', 'E', 'E']]
click = [3, 0]
-
Click Handling:
The click is on[3, 0]
, which is'E'
. Since it’s not a mine, we start our DFS. -
Counting Adjacent Mines at [3,0]:
Check all 8 directions. If no mines are found, mark[3,0]
as'B'
and recursively process its neighbors. -
Recursive Reveal:
Continue this process for every cell reached. When a cell has adjacent mines, update that cell with the count (for example, if there is one adjacent mine, it becomes'1'
) and do not expand further from that cell. -
Termination:
The recursion stops when all reachable cells have either been marked as'B'
or updated with a digit. The final board is then returned.
Common Mistakes
-
Not Checking Boundaries:
When iterating over adjacent cells, always ensure you do not access indices outside the board. -
Overlapping Recursion:
Failing to update a cell immediately after processing can lead to repeated DFS calls on the same cell. Make sure to update and then mark cells to avoid cycles. -
Incorrect Direction Handling:
It’s important to cover all 8 directions. Omitting one or miscalculating an adjacent index can lead to wrong mine counts.
Edge Cases & Alternative Variations
-
Edge Case 1:
Clicking on a mine (cell'M'
). The expected behavior is to update that cell to'X'
immediately. -
Edge Case 2:
A board where all cells are already revealed or have no unrevealed cells left. Although not common, ensure your solution gracefully handles such cases. -
Alternative Variation:
Some variations might require counting adjacent mines differently (for example, considering only four directions instead of eight). Adjust the direction array accordingly.
Related Problems for Further Practice
- Flood Fill:
Similar recursive expansion of cells based on conditions. - Number of Islands:
Use DFS/BFS to traverse 2D grids. - Walls and Gates:
Propagate distances in a 2D grid. - Game of Life:
Update board states based on neighboring cell counts.
GET YOUR FREE
Coding Questions Catalog
