# Time: O(m*n) # Space: O(m*n) class Solution: def gameOfLife(self, board: List[List[int]]) -> None: """ Do not return anything, modify board in-place instead. """ nrows, ncols = len(board), len(board[0]) board_copy = [[None] * ncols for _ in range(nrows)] for i in range(nrows): for j in range(ncols): board_copy[i][j] = next_cell_state(board, i, j) # Copy new board values for i in range(nrows): for j in range(ncols): board[i][j] = board_copy[i][j] def next_cell_state(board, i, j): current = board[i][j] total_alive = sum(get_cell_neighbours(board, i, j)) # Rule 4: Exact 3 neighbors will mean dead cell becomes alive # Live cell remains live if total_alive == 3: return 1 # Rule 2: Live cell lives onto next generation # Dead cell remains dead elif total_alive == 2: return current # Rules 1 and 2: Under-population and over-population return 0 # Return cell at (i, j) or 0 if it's out of bounds def cell(board, i, j): nrows, ncols = len(board), len(board[0]) return board[i][j] if 0 <= i < nrows and 0 <= j < ncols else 0 # Get surrounding 8 neighbours of cell at (i, j) def get_cell_neighbours(board, i, j): return ( cell(board, i - 1, j - 1), cell(board, i - 1, j), cell(board, i - 1, j + 1), cell(board, i, j - 1), cell(board, i, j + 1), cell(board, i + 1, j - 1), cell(board, i + 1, j), cell(board, i + 1, j + 1) )