Skip to the content.

leetcode [289] 生命游戏


Contact me:

Blog -> https://cugtyt.github.io/blog/index
Email -> cugtyt@qq.com
GitHub -> Cugtyt@GitHub


根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在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]
]

进阶:

你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?

参考题解:

死活只使用0和1,可以用10位数表示将来是否死活

class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        def nn(i, j):
            count = 0
            for x, y in [
                [i - 1, j], [i + 1, j], 
                [i, j - 1], [i, j + 1],
                [i - 1, j - 1], [i + 1, j - 1], 
                [i - 1, j + 1], [i + 1, j + 1],
            ]:
                if 0 <= x < len(board) and 0 <= y < len(board[0]) and board[x][y] % 10 == 1:
                    count += 1
            return count

        for i in range(len(board)):
            for j in range(len(board[0])):
                count = nn(i, j)
                if board[i][j] % 10 == 1:
                    if count < 2:
                        board[i][j] = 1
                    if count in [2, 3]:
                        board[i][j] = 11
                    if count > 3:
                        board[i][j] = 1
                else:
                    if count == 3:
                        board[i][j] = 10
        for i in range(len(board)):
            for j in range(len(board[0])):
                board[i][j] = board[i][j] // 10