力扣——生命游戏
根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞具有一个初始状态 live(1)即为活细胞, 或 dead(0)即为死细胞。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。
示例:
输入: [ [0,1,0], [0,0,1], [1,1,1], [0,0,0] ] 输出: [ [0,0,0], [1,0,1], [0,1,1], [0,1,0] ]
进阶:
- 你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
- 本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
class Solution { //第一遍遍历,将1并且周围有两个或三个1的位置设为-1,-1表示这个位置细胞是死的,先设为-1,后面再设为0 //第二遍遍历,将0并且周围有三个1的位置设为2,2表示这个位置细胞是活的,先设为2,后面再设为1 //第三遍遍历,将所有-1设为0,所有2设为1 //计算周围活着的细胞个数时,取1或-1的绝对值 public void gameOfLife(int[][] board) { for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { int count = count(board, i, j); if (board[i][j] == 1 && count != 2 && count != 3) { board[i][j] = -1; } } } for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { int count = count(board, i, j); if (board[i][j] == 0 && count == 3) { board[i][j] = 2; } } } for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (board[i][j] == -1) { board[i][j] = 0; }else if(board[i][j] == 2) { board[i][j] = 1; } } } } private int count(int[][] board, int row, int col) { int liveAround = 0; int rowMax = row + 1 > board.length - 1 ? board.length - 1 : row + 1; int colMax = col + 1 > board[0].length - 1 ? board[0].length - 1 : col + 1; int rowMin = row - 1 < 0 ? 0 : row - 1; int colMin = col - 1 < 0 ? 0 : col - 1; for (int i = rowMin; i >= 0 && i <= rowMax; i++) { for (int j = colMin; j >= 0 && j <= colMax; j++) { if (!(row == i && col == j) && Math.abs(board[i][j]) == 1) { liveAround++; } } } return liveAround; } }