题目描述
根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。
示例一:
输入: 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]]
解题思路
定义一个函数来获取当前数字的周围细胞的存活情况,并且判断周围的位置是否存在。定义一个标记列表,将最开始的细胞的存活情况记录下来,在遍历过程中,根据周围活细胞个数进行修改当前位置的细胞存活状态。最后再遍历一遍标记列表,根据对应的结果修改原格子中的数字。
代码实现
# 定义一个函数 获取当前位置的周围数字
def get_surrouding_numbers(matrix, i, j):
numbers = []
for row in range(i-1, i+2):
for col in range(j-1, j+2):
# 跳过当前数字本身
if row == i and col == j:
continue
# 检查某个数字在矩阵中的位置是否合法
# 不能超过格子的行列范围
# 例如处于边界的数字,它周围的有效数字会少于8个
if 0 <= row < len(matrix) and 0 <= col < len(matrix[0]):
numbers.append(matrix[row][col])
return numbers
def gameOfLife(self, board: List[List[int]]) -> List[List[int]]:
rows = len(board)
cols = len(board[0])
# 初始化一个二维bool列表,用于标记细胞是否存活的过程
ifLife = [[False]*cols for _ in range(rows)]
# 第一次遍历给定的格子,目的为将细胞初状态赋值给标记列表
for i in range(0,rows):
for j in range(0,cols):
# 根据原列表的状态进行赋值
if board[i][j] == 1:
ifLife[i][j] = True
# 第二次遍历给定的格子
for i in range(0,rows):
for j in range(0,cols):
# 获取某个数字周围8个位置的数字,保存在列表中
eight_lists = get_surrouding_numbers(borad, i, j)
# .count()返回列表中指定值的个数
live_cells = eight_lists.count(1)
die_cells = eight_lists.count(0)
# 根据题目条件进行判断
if board[i][j] == 1 and (live_cells<2 or live_cells >3):
ifLife[i][j] = False
elif board[i][j] == 0 and live_cells == 3:
ifLife[i][j] = True
print(f"ifLive改变后:{ifLife}")
# 最后一次遍历 根据改变后的细胞状态,修改格子中的数字
for i in range(0,rows):
for j in range(0,cols):
if ifLife[i][j]==True:
board[i][j] = 1
else:
board[i][j] = 0
return board
# 最后由于题目规定了格子范围,即m行n列的格子中,1 <= m, n <= 25
# 因此即使有4层for循环,且最后两层for循环的次数为3x3,所以其时间复杂度依然在O(mn)范围,不会发生超时