题目要求

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?

这个内容在维基百科上讲述的非常详细,有图文示例。
这个游戏玩家在游戏开始后是不能操作的,完全是由最初的状态来决定最终的结果。板上的每个小格子有两种状态,livedead
而根据游戏规则,每一次这个板上的内容将会随着前一次板上的内容发生变化。变化的规则如下:

  • 如果当前格子为live,那么只要它周围live邻居的数量大于3个或是小于2个,该格子就会变成dead状态。
  • 如果当前个字为dead,那么只要它周围live的邻居数量正好为3个,该格子就会变成live状态。否则还是dead状态。

现在输入一个状态,让我们更新出板子的下一个状态。

思路和代码

这里其实用暴力查询的话也是可以解决的。也就是每遇到一个格子就将该格子的邻居统统遍历一下,计算一个邻居里面live和dead的数量。然后再根据当前格子的状态计算当前格子的下一个状态。但是这里需要一个新的m*n的数组来保存新的状态,有点浪费空间。而且不能很好的利用之前的遍历结果。所以我们可以将之前的遍历结果用某种方式直接存到当前的格子里,减少一些遍历次数。

假设现在有这样的一个board:

[
 [1,0,1],
 [0,0,1],
 [1,1,0],
]

我们从左上角开始遍历,我们发现它的周围一个live的邻居都没有,因此它的状态将会变为0。但是与此同时,它的上一个状态为1,需要传递给周围的邻居,因此我们可以采用将周围邻居+10的方式传递。如下:

[
 [0,10,1],
 [10,10,1],
 [1,1,0],
]

这是我们再看坐标为(0,1)的格子。假设当前个字上的值为cur,那么cur/10则是之前邻居的数量,cur%10则代表该格子的初始状态。根据这个规律,我们可以知道当前格子上的初始状态为0即dead,而之前遍历过的邻居有1个。这时我们就无需遍历所有的邻居,只需要继续访问还未访问的邻居即可。当然最后别忘了将原始状态传递出去。

代码如下:

    public void gameOfLife(int[][] board) {
       if(board==null || board.length==0) return;
       int row = board.length;
       int column = board[0].length;
       int multiply = 10;
       for(int i = 0 ; i<row ; i++){
           for(int j = 0 ; j<column ; j++){
               int cur = board[i][j];
               int liveNeighboars = board[i][j] / multiply;
               if(j+1<column && isLive(board[i][j+1])){
                   liveNeighboars++;
               }
               if(i+1<row){
                   if(j-1>=0 && isLive(board[i+1][j-1])){liveNeighboars++;}
                   if(j+1<column && isLive(board[i+1][j+1])){liveNeighboars++;}
                   if(isLive(board[i+1][j])){liveNeighboars++;}
               }
               if(isLive(cur)){
                   if(liveNeighboars<2 || liveNeighboars>3){
                       board[i][j] = 0;
                   }else{
                       board[i][j] = 1;
                   }
                   if(j+1<column) board[i][j+1] += multiply;
                   if(i+1<row) board[i+1][j] += multiply;
                   if(j-1>=0 && i+1<row) board[i+1][j-1] += multiply;
                   if(j+1<column && i+1<row) board[i+1][j+1] += multiply;
               }else if(liveNeighboars==3){
                   board[i][j] = 1;
               }else{
                   board[i][j] = 0;
               }
           }
       }
    }
    
    public boolean isLive(int number){
        return number % 10 == 1;
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行