leetcode 529 扫雷游戏

241 阅读1分钟

这个题目还是一道模版题,我这里用的是bfs实现,

实现的要点:

  1. 这个题的bfs 是图的bfs 不是二叉树的bfs,所以一定要有一个visited 来标记之前访问过的节点 不然很容易就死循环了

  2. 上下左右以及对角线4个点 一共是8个方向 可以用2个数组来实现, 这样逻辑上可以更清晰

3.这个题虽然我做出来了,但是也有没想通的地方

image.png

例如上图中 为啥结果会有一个E 没有被点出来? 这里难道不应该是一个1吗?

public char[][] updateBoard(char[][] board, int[] click) {
    int rowSize = board.length;
    int colSize = board[0].length;
    // 如果挖到地雷就直接结束
    if (board[click[0]][click[1]] == 'M') {
        board[click[0]][click[1]] = 'X';
        return board;
    }
    boolean[][] visited = new boolean[rowSize][colSize];
    Queue<int[]> queue = new LinkedList<>();
    queue.offer(click);
    // 图的bfs一定要有visited 否则可能会一直在循环里走不出来
    visited[click[0]][click[1]] = true;

    //左上,上 ,右上,左,右,左下,右下,下
    int[] dRow = {-1, -1, -1, 0, 0, 1, 1, 1};
    int[] dCol = {-1, 0, 1, -1, 1, -1, 1, 0};
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int[] cur = queue.poll();
            // 如果挖到空地
            // 默认的相邻地块为地雷的数量
            int mSize = 0;
            for (int j = 0; j < 8; j++) {
                int r = cur[0] + dRow[j];
                int c = cur[1] + dCol[j];
                if (r < 0 || c < 0 || r >= rowSize || c >= colSize) {
                    continue;
                }
                if (board[r][c] == 'M') {
                    mSize++;
                }
            }
            if (mSize != 0) {
                board[cur[0]][cur[1]] = (mSize + "").toCharArray()[0];
            } else {
                board[cur[0]][cur[1]] = 'B';
                for (int j = 0; j < 8; j++) {
                    int r = cur[0] + dRow[j];
                    int c = cur[1] + dCol[j];
                    if (r < 0 || c < 0 || r >= rowSize || c >= colSize || visited[r][c] || board[r][c] != 'E') {
                        continue;
                    }
                    queue.offer(new int[]{r, c});
                    visited[r][c] = true;
                }
            }

        }
    }
    return board;
}