力扣-289.生命游戏

61 阅读2分钟

给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

  1. 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
  2. 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
  3. 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
  4. 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。

示例 1:

输入: board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
输出: [[0,0,0],[1,0,1],[0,1,1],[0,1,0]]

示例 2:

输入: board = [[1,1],[1,0]]
输出: [[1,1],[1,1]]

遍历每个细胞,统计这个位置周围的活细胞数量(八个方向)。

在遍历的过程中,可能出现上方的0/1被修改,影响下方的判断

这个问题可以通过加入新状态来解决,定义2表示0->1 ; 3表示1->0. 不变则不修改

public void gameOfLife(int[][] board) {
        int m = board.length;
        int n = board[0].length;
        int[][] dir = new int[][]{{-1,0},{1,0},{0,1},{0,-1},{-1,1},{-1,-1},{1,-1},{1,1}}; //八个位置
        for (int i = 0; i < m; i++){
            for (int j = 0; j < n; j++){
                int num = 0; //统计[i,j]位置处活细胞数量
                for (int p = 0; p < 8; p++){
                    int dx = i + dir[p][0];
                    int dy = j + dir[p][1];
                    if (dx < 0 || dy < 0 || dx >= m || dy >= n) continue;
                    if (board[dx][dy] == 1 || board[dx][dy] == 3) num++;
                }
                //判断该位置是死细胞还是活细胞
                if (board[i][j] == 1) {
                    if (num < 2 || num > 3){
                        board[i][j] = 3;
                    }
                } else if (num == 3) {
                    board[i][j] = 2;
                }
            }
        }
        //复原2和3状态
        for (int i = 0; i < m ; i++){
            for (int j = 0; j < n; j++){
                if (board[i][j] == 2) board[i][j] = 1;
                else if (board[i][j] == 3) board[i][j] = 0;
            }
        }
    }