题目:
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):
- Any live cell with fewer than two live neighbors dies, as if caused by under-population.
- Any live cell with two or three live neighbors lives on to the next generation.
- Any live cell with more than three live neighbors dies, as if by over-population..
- Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
Follow up:
- Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
- In this question, we represent the board using a 2D array. 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?
英国数学家发明的生命游戏:使用一个2维数组来实现其规则,在这个数组中,每个存储位子都能容纳一个LIFE元胞。世代用于标记时间的流逝。每个世代都会LIFE社会带来生与死。生死的规则如下:
1.定义的元胞都有八个邻居。上下左右,左上左下,右上右下八个方位。
2.如果一个元胞有一个或者零个邻居,会因为孤独而死亡。3个以上的邻居会因为拥挤拥挤而死亡
3.如果空元胞正好有3个邻居,会在空元胞的位子生成一个元胞
4.生生死死世代交换
解题思路:
初始的想法就是copy原来的数组矩阵,然后修改原来的矩阵,如果这样做会使用O(m*n)的space。
如何做到in-place呢,需要根据改动前的状态数出live cell的个数,已经更改的点如何知道原有的状态呢。就要多mark出几种conditions.
Dead->Dead:condition 0 ;LIve->Live:condition 1;Live->Dead:condition 2;Dead->Live:condition 3
如此在数数的时候如果原道1 和 2 他们的原有的状态都是Live,就都要算。
最后通过把所有的数%2来得到更改后的状态。
如何理解这四种状态?第一 是如此顺序是因为0本身就是dead cell,1本身就是live cell,如此在count live完成后可以尽量少改动数组,如果是live的1的状态就不用动了;第二是最后对 0,1,2改回0,1时 可以直接通过% 2改动省事。如果需要记住原有的状态就可以通过增加condition来搞定。
Time Complexiy:O(m*n),Space:O(1).
代码:
public class Solution {
public void gameOfLife(int[][] board) {
int m = board.length;
int n = board[0].length;
if(board == null || m == 0 || n == 0){
return;
}
for(int i = 0;i < m; i++){
for(int j = 0; j < n;j++){
int count = getLive(board,i,j);
if(board[i][j]==0 && count ==3){
board[i][j]=3;
}else if(board[i][j] == 1 && (count < 2 || count > 3)){
board[i][j]=2;
}
}
}
for(int i = 0;i < m ; i ++){
for(int j = 0; j < n;j++){
board[i][j] = board[i][j] % 2;
}
}
}
public int getLive(int[][]board,int i,int j){
int count = 0;
for(int x = i-1;x <= i+1;x++){
for(int y = j-1;y<=j+1;y++){
if(x < 0||x>=board.length||y < 0||y>=board[0].length||(i==x && j==y)){
continue;
}
if(board[x][y]==1 || board[x][y] == 2){
count++;
}
}
}
return count;
}
}
public void gameOfLife(int[][] board) {
int m = board.length;
int n = board[0].length;
if(board == null || m == 0 || n == 0){
return;
}
for(int i = 0;i < m; i++){
for(int j = 0; j < n;j++){
int count = getLive(board,i,j);
if(board[i][j]==0 && count ==3){
board[i][j]=3;
}else if(board[i][j] == 1 && (count < 2 || count > 3)){
board[i][j]=2;
}
}
}
for(int i = 0;i < m ; i ++){
for(int j = 0; j < n;j++){
board[i][j] = board[i][j] % 2;
}
}
}
public int getLive(int[][]board,int i,int j){
int count = 0;
for(int x = i-1;x <= i+1;x++){
for(int y = j-1;y<=j+1;y++){
if(x < 0||x>=board.length||y < 0||y>=board[0].length||(i==x && j==y)){
continue;
}
if(board[x][y]==1 || board[x][y] == 2){
count++;
}
}
}
return count;
}
}