• [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 - 未发现的雷
    • 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 题目总结

  • 相关阅读:
    [转]调试winlogon
    [转]整理一份我对Windows文件系统过滤驱动的sFilter工程代码的详细说明
    [转]在内核调试会话中设置用户态断点
    用Windbg调试GINA
    [转]文件过滤驱动开发
    [转]NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别
    [转]windbg下在kd模式也可以调试用户模式程序
    ProgressDialog多了一个外边框
    Dx trouble processing "java/nio/CharBuffer.class":
    ImageView图片重叠问题
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13365574.html
Copyright © 2020-2023  润新知