1.题目描述
根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在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]
]
进阶:你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
2.解题思路
题目给了我们一个2d array,让我们根据game of life 的规则,改变cells,进行到下一个 状态。
规定了我们要in-place改动,但是问题在于,题目中要求所有的位置必须被同时更新,但在循环程序中还是一个位置一个位置更新的,每一个cell 的改动都依赖于它周围8个的cell的情况,所以前面被改动的cell会影响后面的cell的判断,肯定会造成错误。
根据题目描述,我们首先要查看一个细胞周围live的个数,如果周围的cell 已经被改动过了,我们需要看的是它之前的状态(是否是live的)。根据live的个数来改变细胞的状态。
我们要想出一种方法,就是,改动完了的cell,我们查看它的情况,依然能够知道那个cell 之前的state。
对于每一个cell, 可以建立 4种情况:
0 dead -> dead 没有变化
1 live -> live 没有变化
2 live -> dead 从live 变为 dead
3 dead -> live 从dead 变为live
1.我们首先要查看一个细胞周围live的个数
那么我们看,红色的是初始的状态,蓝色的是改动过的状态,因为我们只需要查看live的个数, 不管它有没有被改动过,我们只看红色部分就对了,因为我们要的是它初始的状态,那么只可能是1 和 2。所以我们只需要查看所有cell 是1 或者是 2的,来count 一共有几个live neighbors。
2.然后根据live的个数来改变细胞的状态
对于情况0 和1, 因为没有变化,所以每个cell 的值 还是 0 和 1,无需做出改变;
对于剩下2种情况:如果是从 live 变为 dead(题目中的规则1和3), 就把值改成2; 如果是从 dead 变为 live(规则4), 就把值改成3。
参考链接:
https://www.cnblogs.com/jimmycheng/p/7530366.html
https://www.cnblogs.com/grandyang/p/4854466.html
3.代码实现
class Solution(object):
def gameOfLife(self, board):
"""
:type board: List[List[int]]
:rtype: None Do not return anything, modify board in-place instead.
"""
"""
0 dead -> dead 没有变化
1 live -> live 没有变化
2 live -> dead 从live 变为 dead
3 dead -> live 从dead 变为live
"""
m=len(board)
n=len(board[0])
dx=[-1, -1, -1, 0, 1, 1, 1, 0]
dy=[-1, 0, 1, 1, 1, 0, -1, -1]
for i in range(m):
for j in range(n):
cnt = 0
for k in range(8):
x = i + dx[k]
y = j + dy[k]
if x >= 0 and x < m and y >= 0 and y < n and (board[x][y] == 1 or board[x][y] == 2):
cnt+=1
if board[i][j] == 1 and (cnt < 2 or cnt > 3):
board[i][j] = 2
if board[i][j] == 0 and cnt == 3:
board[i][j] = 3
for i in range(m):
for j in range(n):
board[i][j] %= 2
return board