1. 问题描述:
根据百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 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]]
输入:board = [[1,1],[1,0]]
输出:[[1,1],[1,1]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 25
board[i][j] 为 0 或 1
进阶:
你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/game-of-life
2. 思路分析:
分析题目可以知道我们模拟整个过程即可,但是由于不能开额外的空间来存储结果,所以我们需要使用其他的方法。因为board存储的是32位二进制数字的一位,所以每个存储空间只是使用到了一位二进制数字,所以我们可以充分利用这个特点,遍历当前的矩阵board[i][j]周围的八个相邻的元素,计算出周围八个位置的活的细胞数目,根据当前位置周围八个位置活的细胞数目将当前boardp[i][j]值更新为题目说的对应的状态,因为第一位已经使用了所以我们需要将结果更新到board[i][j]对应二进制数字的第二位,更新的时候使用位运算的移位操作即可。最后需要再遍历一遍board列表,将二进制的第二位右移一位那么就是最终的答案了。
3. 代码如下:
from typing import List
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
r, c = len(board), len(board[0])
if r == 0 or c == 0: return
for i in range(r):
for j in range(c):
live = 0
for m in range(max(0, i - 1), min(r, i + 2)):
for n in range(max(0, j - 1), min(c, j + 2)):
# 这里需要排除掉当前自己的位置
if (m != i or n != j) and board[m][n] & 1:
live += 1
cur, next = board[i][j] & 1, 0
if cur:
if live < 2 or live > 3:
next = 0
else:
next = 1
else:
if live == 3:
next = 1
else:
next = 0
board[i][j] |= (next << 1)
# 更新列表的状态
for m in range(r):
for n in range(c):
board[m][n] >>= 1