[LeetCode] 529. Minesweeper

Let's play the minesweeper game (Wikipediaonline game)!

You are given a 2D char matrix representing the game board. 'M' represents an unrevealed mine, 'E' represents an unrevealed empty square, 'B' represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit ('1' to '8') represents how many mines are adjacent to this revealed square, and finally 'X' represents a revealed mine.

Now given the next click position (row and column indices) among all the unrevealed squares ('M' or 'E'), return the board after revealing this position according to the following rules:

  1. If a mine ('M') is revealed, then the game is over - change it to 'X'.
  2. If an empty square ('E') with no adjacent mines is revealed, then change it to revealed blank ('B') and all of its adjacent unrevealed squares should be revealed recursively.
  3. If an empty square ('E') with at least one adjacent mine is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines.
  4. Return the board when no more squares will be revealed.

Example 1:

Input: 

[['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:

Example 2:

Input: 

[['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:

Note:

  1. The range of the input matrix's height and width is [1,50].
  2. The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square.
  3. The input board won't be a stage when game is over (some mines have been revealed).
  4. For simplicity, not mentioned rules should be ignored in this problem. For example, you don't need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.

扫雷游戏。

让我们一起来玩扫雷游戏!

给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中:

'M' 代表一个 未挖出的 地雷,
'E' 代表一个 未挖出的 空方块,
'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的 已挖出的 空白方块,
数字('1' 到 '8')表示有多少地雷与这块 已挖出的 方块相邻,
'X' 则表示一个 已挖出的 地雷。
给你一个整数数组 click ,其中 click = [clickr, clickc] 表示在所有 未挖出的 方块('M' 或者 'E')中的下一个点击位置(clickr 是行下标,clickc 是列下标)。

根据以下规则,返回相应位置被点击后对应的盘面:

如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X' 。
如果一个 没有相邻地雷 的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的 未挖出 方块都应该被递归地揭露。
如果一个 至少与一个地雷相邻 的空方块('E')被挖出,修改它为数字('1' 到 '8' ),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回盘面。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minesweeper
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

游戏本身我们小时候应该都玩过,我这里提炼以下题目里面的字母和规则吧。

  • M - 未发现的雷
  • E - 未发现的空白方块
  • B - 发现的空白方块
  • 数字 1 - 8
  • X - 发现了的雷

这个题我做的时候个人觉得规则解释的不是非常明确,虽然题目说了没有提到的规则可以被忽略(Note 4)。题目给的是二维矩阵board和其中的某一个坐标click。如果当前click位置上点开是个雷,把他mark成X,然后直接就返回board了。例子二把周围的八个坐标mark成了1,但是如果你只是mark了雷而不mark那些1,也是可以的。另外,比如第一个例子,点开的坐标背后是一个B,但是实际题目要求你是递归地遍历完整个board,这个跟我们小时候玩游戏的时候有一点区别,因为他点一次,直接就要求你把整个board的结果返回了。但是雷正上方的那个坐标却依然保持了E。这个坐标保持E的原因是在于DFS遍历的时候先找到了雷所以就直接返回board了,还没来得及去看那个坐标。

回到这道题的解题思路上。既然题目提示了recursively,那么我们试着用DFS做。不过这道题不同于一般的DFS题,需要遍历当前坐标周围的八个邻居

  • 如果当前坐标是雷,标记成X,立马返回board
  • 如果当前坐标不是雷,遍历其八个邻居,计算一下有几个雷,把雷的数量写在当前坐标上,返回board
  • 如果当前坐标是blank/E,则把当前坐标改成B,然后递归去看他的八个邻居

时间O(mn)

空间O(n)

Java实现

 1 class Solution {
 2     private int[][] dirs = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 }, { -1, -1 }, { 1, 1 }, { 1, -1 }, { -1, 1 } };
 3 
 4     public char[][] updateBoard(char[][] board, int[] click) {
 5         int row = click[0];
 6         int col = click[1];
 7         int m = board.length;
 8         int n = board[0].length;
 9 
10         // if current position is a bomb
11         if (board[row][col] == 'M') {
12             board[row][col] = 'X';
13             return board;
14         }
15 
16         // count the number of bombs
17         int num = 0;
18         for (int[] dir : dirs) {
19             int newRow = dir[0] + row;
20             int newCol = dir[1] + col;
21             if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && board[newRow][newCol] == 'M') {
22                 num++;
23             }
24         }
25 
26         // mark the number of bombs around, then return
27         if (num > 0) {
28             board[row][col] = (char) (num + '0');
29             return board;
30         }
31 
32         // if no bomb, mark it as blank
33         board[row][col] = 'B';
34         for (int[] dir : dirs) {
35             int newRow = dir[0] + row;
36             int newCol = dir[1] + col;
37             if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && board[newRow][newCol] == 'E') {
38                 updateBoard(board, new int[] { newRow, newCol });
39             }
40         }
41         return board;
42     }
43 }

 

flood fill题型总结

LeetCode 题目总结

posted @ 2020-07-23 12:14  CNoodle  阅读(205)  评论(0编辑  收藏  举报