Skip to main content

生命游戏

题目

根据维基百科, 生命游戏, 简称为生命, 是英国数学家 John Horton Conway 在 1970 年发明的细胞自动机.

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

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

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

给定当前 board 的状态, 更新 board 到下一个状态.

注意你不需要返回任何东西.

提示:
  • m == board.length
  • n == board[row].length
  • 1 <= m, n <= 25
  • board[row][col]01
进阶:
  • 你可以使用原地算法解决本题吗? 请注意, 面板上所有格子需要同时被更新: 你不能先更新某些格子, 然后使用它们的更新后的值再更新其他格子.
  • 本题中, 我们使用二维数组来表示面板. 原则上, 面板是无限的, 但当活细胞侵占了面板边界时会造成问题. 你将如何解决这些问题?
示例

289-game-of-life

输入: 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]]

289-game-of-life

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

题解

因为你不能先更新某些格子, 然后使用它们的更新后的值再更新其他格子, 所以可以先把要处理的节点记录下来. 具体来讲:

  1. 遍历每个元素, 找到所有包围它的周边元素, 统计是 1 的个数

  2. 第二次遍历, 根据题目要求模拟, 决定该元素需要:

    • 从生存到死亡
    • 从死亡到复活
    • 不处理
/**
* @param {number[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var gameOfLife = function (board) {
const m = board.length
const n = board[0].length

const lives = new Array(m).fill().map(() => new Array(n).fill(0))
for (let row = 0; row < m; row++) {
for (let col = 0; col < n; col++) {
for (let i = Math.max(row - 1, 0); i <= Math.min(row + 1, m - 1); i++) {
for (let j = Math.max(col - 1, 0); j <= Math.min(col + 1, n - 1); j++) {
if (i === row && j === col) continue

if (board[i][j] === 1) {
lives[row][col] += 1
}
}
}
}
}

for (let row = 0; row < m; row++) {
for (let col = 0; col < n; col++) {
if (board[row][col] === 1) {
if (lives[row][col] < 2 || lives[row][col] > 3) {
board[row][col] = 0
}
} else {
if (lives[row][col] === 3) {
board[row][col] = 1
}
}
}
}
}