comments | difficulty | edit_url | tags | |||
---|---|---|---|---|---|---|
true |
中等 |
|
根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n
个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1
即为 活细胞 (live),或 0
即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是 同时 发生的。给你 m x n
网格面板 board
的当前状态,返回下一个状态。
给定当前 board
的状态,更新 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]]
示例 2:
输入: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
进阶:
- 你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
- 本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
我们不妨定义两个新的状态,其中状态
因此,我们可以遍历整个面板,对于每个格子,统计其周围的活细胞数目,用变量
最后,我们再遍历一遍面板,将状态
时间复杂度
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
m, n = len(board), len(board[0])
for i in range(m):
for j in range(n):
live = -board[i][j]
for x in range(i - 1, i + 2):
for y in range(j - 1, j + 2):
if 0 <= x < m and 0 <= y < n and board[x][y] > 0:
live += 1
if board[i][j] and (live < 2 or live > 3):
board[i][j] = 2
if board[i][j] == 0 and live == 3:
board[i][j] = -1
for i in range(m):
for j in range(n):
if board[i][j] == 2:
board[i][j] = 0
elif board[i][j] == -1:
board[i][j] = 1
class Solution {
public void gameOfLife(int[][] board) {
int m = board.length, n = board[0].length;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int live = -board[i][j];
for (int x = i - 1; x <= i + 1; ++x) {
for (int y = j - 1; y <= j + 1; ++y) {
if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] > 0) {
++live;
}
}
}
if (board[i][j] == 1 && (live < 2 || live > 3)) {
board[i][j] = 2;
}
if (board[i][j] == 0 && live == 3) {
board[i][j] = -1;
}
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 2) {
board[i][j] = 0;
} else if (board[i][j] == -1) {
board[i][j] = 1;
}
}
}
}
}
class Solution {
public:
void gameOfLife(vector<vector<int>>& board) {
int m = board.size(), n = board[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int live = -board[i][j];
for (int x = i - 1; x <= i + 1; ++x) {
for (int y = j - 1; y <= j + 1; ++y) {
if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] > 0) {
++live;
}
}
}
if (board[i][j] == 1 && (live < 2 || live > 3)) {
board[i][j] = 2;
}
if (board[i][j] == 0 && live == 3) {
board[i][j] = -1;
}
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 2) {
board[i][j] = 0;
} else if (board[i][j] == -1) {
board[i][j] = 1;
}
}
}
}
};
func gameOfLife(board [][]int) {
m, n := len(board), len(board[0])
for i := 0; i < m; i++ {
for j, v := range board[i] {
live := -v
for x := i - 1; x <= i+1; x++ {
for y := j - 1; y <= j+1; y++ {
if x >= 0 && x < m && y >= 0 && y < n && board[x][y] > 0 {
live++
}
}
}
if v == 1 && (live < 2 || live > 3) {
board[i][j] = 2
}
if v == 0 && live == 3 {
board[i][j] = -1
}
}
}
for i := 0; i < m; i++ {
for j, v := range board[i] {
if v == 2 {
board[i][j] = 0
}
if v == -1 {
board[i][j] = 1
}
}
}
}
/**
Do not return anything, modify board in-place instead.
*/
function gameOfLife(board: number[][]): void {
const m = board.length;
const n = board[0].length;
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
let live = -board[i][j];
for (let x = i - 1; x <= i + 1; ++x) {
for (let y = j - 1; y <= j + 1; ++y) {
if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] > 0) {
++live;
}
}
}
if (board[i][j] === 1 && (live < 2 || live > 3)) {
board[i][j] = 2;
}
if (board[i][j] === 0 && live === 3) {
board[i][j] = -1;
}
}
}
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
if (board[i][j] === 2) {
board[i][j] = 0;
}
if (board[i][j] === -1) {
board[i][j] = 1;
}
}
}
}
const DIR: [(i32, i32); 8] = [
(-1, 0),
(1, 0),
(0, -1),
(0, 1),
(-1, -1),
(-1, 1),
(1, -1),
(1, 1),
];
impl Solution {
#[allow(dead_code)]
pub fn game_of_life(board: &mut Vec<Vec<i32>>) {
let n = board.len();
let m = board[0].len();
let mut weight_vec: Vec<Vec<i32>> = vec![vec![0; m]; n];
// Initialize the weight vector
for i in 0..n {
for j in 0..m {
if board[i][j] == 0 {
continue;
}
for (dx, dy) in DIR {
let x = (i as i32) + dx;
let y = (j as i32) + dy;
if Self::check_bounds(x, y, n as i32, m as i32) {
weight_vec[x as usize][y as usize] += 1;
}
}
}
}
// Update the board
for i in 0..n {
for j in 0..m {
if weight_vec[i][j] < 2 {
board[i][j] = 0;
} else if weight_vec[i][j] <= 3 {
if board[i][j] == 0 && weight_vec[i][j] == 3 {
board[i][j] = 1;
}
} else {
board[i][j] = 0;
}
}
}
}
#[allow(dead_code)]
fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool {
i >= 0 && i < n && j >= 0 && j < m
}
}
public class Solution {
public void GameOfLife(int[][] board) {
int m = board.Length;
int n = board[0].Length;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int live = -board[i][j];
for (int x = i - 1; x <= i + 1; ++x) {
for (int y = j - 1; y <= j + 1; ++y) {
if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] > 0) {
++live;
}
}
}
if (board[i][j] == 1 && (live < 2 || live > 3)) {
board[i][j] = 2;
}
if (board[i][j] == 0 && live == 3) {
board[i][j] = -1;
}
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 2) {
board[i][j] = 0;
}
if (board[i][j] == -1) {
board[i][j] = 1;
}
}
}
}
}