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.
Follow up:
这道题难点在于不能使用额外的空间,只能在它给予的 board 上作修改。
为了在原有的数组空间中解决该问题,我们使用 2 bits 来存储 4 个状态:
[2nd bit, 1st bit] = [next state, current state]
- 00 dead (next) <- dead (current) 状态0:死->死
- 01 dead (next) <- live (current) 状态1:活->死
- 10 live (next) <- dead (current) 状态2:死->活
- 11 live (next) <- live (current) 状态3:活->活
要得到 board[i][j] 的当前状态,只需要如下操作。奇数 代表当前状态是 活的,偶数 代表当前状态是 死的。
board[i][j] % 2
要得到 board[i][j] 的下一个状态,只需要如下操作。≥2 代表下一状态是 活的,<2 代表下一状态是 死的。
board[i][j] / 2
//活->活=3 活->死=1
//死->死=0 死->活=2
public void gameOfLife(int[][] board) {
if(board.length==0||board[0].length==0){
return;
}
int m=board.length;
int n=board[0].length;
for(int i=0;i3){
board[i][j]=1; //活->死
}
else{
board[i][j]=3; //活->活
}
}
else{ //如果当前cel是死着的
if(liveNeighbors==3){
board[i][j]=2; //死->活
}
else{
board[i][j]=0; //死->死
}
}
}
}
for(int i=0;i=m||y<0||y>=n){
continue;
}
if(board[x][y]%2==1){
count++;
}
}
return count;
}
对于follow-up问题中的:In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
大神表示:Instead of 使用 1,0 二维数组,而是使用 live cell 坐标集合 来表示该 board。
在 set 中存放的是所有活着的细胞的坐标集合。那么如何计算 活着的邻居个数 呢?可以遍历 live cell 集合,然后增加它们邻居的计数器(所以那些没有活着邻居的细胞将不会出现在这个计数器中)。最后,我们通过提取那些拥有正确数量活着邻居的细胞,来放入新的 live cell 集合。
private Set getNewLives(Set live) {
Map neighbours = new HashMap<>();
for (Coord cell : live) {
for (int i = cell.i-1; i2; i++) {
for (int j = cell.j-1; j2; j++) {
if (i==cell.i && j==cell.j) continue;
Coord c = new Coord(i,j);
if (neighbours.containsKey(c)) {
neighbours.put(c, neighbours.get(c) + 1);
} else {
neighbours.put(c, 1);
}
}
}
}
Set newLive = new HashSet<>();
for (Map.Entry cell : neighbours.entrySet()) {
if (cell.getValue() == 3 || cell.getValue() == 2 && live.contains(cell.getKey())) {
newLive.add(cell.getKey());
}
}
return newLive;
}
where Coord is:
private static class Coord {
int i;
int j;
private Coord(int i, int j) {
this.i = i;
this.j = j;
}
public boolean equals(Object o) {
return o instanceof Coord && ((Coord)o).i == i && ((Coord)o).j == j;
}
public int hashCode() {
int hashCode = 1;
hashCode = 31 * hashCode + i;
hashCode = 31 * hashCode + j;
return hashCode;
}
}
and the wrapper:
public void gameOfLife(int[][] board) {
Set live = new HashSet<>();
int m = board.length;
int n = board[0].length;
for (int i = 0; ifor (int j = 0; jif (board[i][j] == 1) {
live.add(new Coord(i,j));
}
}
};
live = getNewLives(live);
for (int i = 0; ifor (int j = 0; jnew Coord(i,j))?1:0;
}
};
}