05 August 2008
According to the Wikipedia’s article: “The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.”
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
Write a function to compute the next state (after one update) of the board given its current state. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Input:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
Output:
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]
Follow up:
参考这里和这里,用二维数组来表示细胞,1代表活细胞,0代表死细胞按照题意,每个细胞满足以下条件:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡
如果死细胞周围正好有三个活细胞,则该位置死细胞复活
要求计算给定的二维数组的下一个状态,在in-place位置更新,所以就不能新建一个相同大小的数组,只能更新原有数组,但是题目中要求所有的位置必须被同时更新,不能分批更新,但是在循环程序中我们还是一个位置一个位置更新的,那么当一个位置更新了,这个位置成为其他位置的neighbor时,我们怎么知道其未更新的状态呢,我们可以使用状态机转换:
状态0: 死细胞转为死细胞
状态1: 活细胞转为活细胞
状态2: 活细胞转为死细胞
状态3: 死细胞转为活细胞
对所有状态对2取余,那么状态0和2就变成死细胞,状态1和3就是活细胞。因此先对原数组进行逐个扫描,对于每一个位置,扫描其周围八个位置,如果遇到状态1或2,就计数器累加1,扫完8个邻居,如果少于两个活细胞或者大于三个活细胞,而且当前位置是活细胞的话,标记状态2,而如果有三个活细胞且当前是死细胞的话,标记状态3。完成一遍扫描后再对数据扫描一遍,对2取余。
****https://leetcode.com/problems/game-of-life/discuss/73223/Easiest-JAVA-solution-with-explanation****
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Solution {
final int[][] dirs = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} };
public void gameOfLife(int[][] board) {
// live: 1
// death: 0
// death -> live: -1
// live -> death: 2
// two passes, the first pass changes all cell's state for memorization, the second pass change back
if (board == null || board.length == 0) {
return;
}
int rows = board.length;
int cols = board[0].length;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 1) {
int livesNearby = calLives(board, i, j);
if (livesNearby < 2 || livesNearby > 3) {
board[i][j] = 2;
}
}
if (board[i][j] == 0) {
int livesNearby = calLives(board, i, j);
if (livesNearby == 3) {
board[i][j] = -1;
}
}
}
}
update(board);
}
private int calLives(int[][] board, int row, int col) {
int livesNearbyCell = 0;
for (int[] dir : dirs) {
int checkingRow = row + dir[0];
int checkingCol = col + dir[1];
if (checkingRow >= 0 &&
checkingRow < board.length &&
checkingCol >= 0 &&
checkingCol < board[0].length &&
(board[checkingRow][checkingCol] == 1 || board[checkingRow][checkingCol] == 2)) {
livesNearbyCell++;
}
}
return livesNearbyCell;
}
private void update(int[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == -1) {
board[i][j] = 1;
} else if (board[i][j] == 2) {
board[i][j] = 0;
}
}
}
}
}