Leetcode 之GameofLife

题目描述:
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?

简而言之:一个矩阵格子,每个格子是一个细胞

如果细胞一开始是活的,满足条件

  • 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.
    时,细胞发生相应变化。

题目虽然是Medium但思路十分简单,就是把每个细胞周围的其他细胞的状态统计一下,再更新就行了。

但是由于我们是用一个二维数组遍历去更新的,当前细胞的变化不能影响到下一个细胞,也就要求我们保存细胞的当前状态以及下一更新状态。

最intuitive的思路就是再建一个和输入完全相同的数组,这个数组不进行更新,只用于统计周围细胞状态。

代码中用( (i-1<0||j-1<0) ? 0 : board_cp[i-1][j-1])
是因为不能肯定board_cp[i-1][j-1]的下标有没有超出数组的界限,如果超界了就取值为0,没超界就使用二维数组本身的值。

但是这样的方法浪费了空间,如果要用inplace的方法,我们可以发现,总共就四个状态:0->0, 0->1, 1->0, 1->1,正好可以用0,1,2,3的二进制表示,二进制第一位用于表示下一状态,第二位表示当前状态,通过位运算num&2==0判断第二位是0 or 1, 通过num&1==0判断第一位是0 or 1。

代码如下(实现了两种方法):


public class GameofLife {

        public void gameOfLife(int[][] board) {
            int m=board.length,n=board[0].length;
            int[][]board_cp=new int[m][n];
            for(int i=0;i<m;i++)
                for(int j=0;j<n;j++)
                    board_cp[i][j]=board[i][j];
            int live,dead;
            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){
                    live=dead=0;
                    live=( (i-1<0||j-1<0) ? 0 : board_cp[i-1][j-1])+( (i-1<0) ? 0 :board_cp[i-1][j])+( (i-1<0||j+1>n-1) ? 0 : board_cp[i-1][j+1])+
                                ( (j-1<0) ? 0 : board_cp[i][j-1])+( (j+1>n-1) ? 0 :board_cp[i][j+1] )+
                                ( (i+1>m-1||j-1<0) ? 0 :board_cp[i+1][j-1])+( (i+1>m-1) ? 0 : board_cp[i+1][j])+( (i+1>m-1||j+1>n-1) ? 0 :board_cp[i+1][j+1]);


                    if (board[i][j]==1){
                        System.out.println("original live");

                        if(live==2||live==3);
                        else board[i][j]=0;
                    }
                    else{
                        System.out.println("original dead");                        
                        if(live==3)board[i][j]=1;
                        else ;
                    }
                    System.out.println("status:"+board[i][j]);

                }
            }
        }
        public void gameOfLife_inplace(int[][] board_cp) {

            int m=board_cp.length,n=board_cp[0].length;
            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){

                    if(board_cp[i][j]==1)board_cp[i][j]=3;
                    else ;
//                  System.out.println((((board_cp[i][j]&2)==0)?0:1));
                }
            }
            int live,dead;
            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){
                    live=dead=0;
                    live=( (i-1<0||j-1<0) ? 0 : ((board_cp[i-1][j-1]&2)==0)?0:1)+( (i-1<0) ? 0 :((board_cp[i-1][j]&2)==0)?0:1)+( (i-1<0||j+1>n-1) ? 0 :( (board_cp[i-1][j+1]&2)==0)?0:1)+
                                ( (j-1<0) ? 0 :( (board_cp[i][j-1]&2)==0)?0:1)+( (j+1>n-1) ? 0 :((board_cp[i][j+1]&2)==0)?0:1 )+
                                ( (i+1>m-1||j-1<0) ? 0 :((board_cp[i+1][j-1]&2)==0)?0:1)+( (i+1>m-1) ? 0 : ((board_cp[i+1][j]&2)==0)?0:1)+( (i+1>m-1||j+1>n-1) ? 0 :((board_cp[i+1][j+1]&2)==0)?0:1);
//                  System.out.println("live:"+live);
                    if (board_cp[i][j]==2||board_cp[i][j]==3){
//                      System.out.println("original live");

                        if(live==2||live==3)board_cp[i][j]=3;
                        else board_cp[i][j]=2;

                    }
                    if (board_cp[i][j]==0||board_cp[i][j]==1){
//                      System.out.println("original dead");

                        if(live==3)board_cp[i][j]=1;
                        else board_cp[i][j]=0;
                    }
//              System.out.println("status:"+(((board_cp[i][j]&1)==0)?0:1));
                }
                }
            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){
                    board_cp[i][j]=(((board_cp[i][j]&1)==0)?0:1);
                }
            }

        }
    public static void main(String[]args){
    GameofLife c=new GameofLife();
    int[][]nums={{1,1},{1,0}};
    c.gameOfLife_inplace(nums);
//System.out.println(~1);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值