题目描述
生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。
每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。
注意:你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
分析:题目说所有格子需要同时更新,可以另外开辟一个二维数组存放,但题目说使用原地算法,所以就原本的二维数组上操作。
定义一个状态发生改变的数组,存放的是修改过的状态的下标。
flag_1_0:表示1->0
flag_0_1:表示0->1
解法一:暴力直观法
def gameOfLife( board):
"""
:type board: List[List[int]]
:rtype: None Do not return anything, modify board in-place instead.
"""
row =len(board)
col = len(board[0])
if row == 0 or col == 0 :
return board
#一个格子附近的八个方向
dire_x = [-1,1,0,0,-1,-1,1,1]
dire_y = [0,0,1,-1,-1,1,-1,1]
flag_1_0= []
flag_0_1= []
for i in range(row):
for j in range(col):
count = 0
for t in range(8):
x = dire_x[t] +i
y = dire_y[t] + j
#判断边界
if x <0 or x >= row or y < 0 or y >= col:
continue
if board[i][j] == 1:
#如果为活细胞,就统计周围死细胞的个数
if board[x][y] == 1 :
if ([x,y] not in flag_0_1) :
count += 1
if board[x][y] == 0 and [x,y] in flag_1_0:
count+= 1
#如果为死细胞
if board[i][j] == 0:
if board[x][y] == 1:
if [x,y] not in flag_0_1:
count +=1
if board[x][y] == 0:
if [x,y] in flag_1_0:
count += 1
if count == 3 and board[i][j]== 0:
flag_0_1.append([i,j])
board[i][j] = 1
if (count < 2 or count >3 ) and board[i][j] == 1 :
flag_1_0.append([i,j])
board[i][j] = 0
return board
解法二:逆向思维
分析:被影响到的格子加10,只有为1 的格子的才能影响周围的8个格子。
规则:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
def gameOfLife(board):
m,n = len(board),len(board[0])
def effect(x,y):
for i in [x-1,x,x+1]:
for j in [y-1,y,y+1]:
if (i ==x and j ==y) or (i < 0 or i >=m or j < 0 or j >= n):
continue
board[i][j] += 10
def change(i,j):
if board[i][j] // 10 == 3:
board[i][j] = 1
elif board[i][j] % 10 == 1 and board[i][j] //10 ==2 :
board[i][j] = 1
else:
board[i][j] = 0
for i in range(m):
for j in range(n):
if board[i][j] %10== 1:
effect(i,j)
#分析影响状况
for i in range(m):
for j in range(n):
change(i,j)