[Leetcode] Game of Life 生命游戏

本文介绍生命游戏(Game of Life)的基本规则及其两种Java实现方法:一种使用额外的二维数组来存储下一代的状态,另一种采用in-place更新策略,通过特殊编码来记录细胞状态的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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?

思路1
普通解法,遍历每一个细胞求值,用一个M*N的矩阵存放结果。
求值过程,稍微分析一下可知,其实就是按照以下的矩阵进行,结果是可数的。

        细胞状态       0    1
        邻居1个数0     0    0
                1     0    0
                2*    0    1
                3*    1    1
                4     0    0
                5     0    0
                6     0    0
                7     0    0
                8     0    0

复杂度
空间(MN),时间(MN)

实现代码1

public class GameofLife {
    
    /**
     * 直接解法    
     * 空间(n)
     * @param board
     * @return
     */
    public int[][] Solution1(int[][] board){
        int m = board.length;s

        int n = board[0].length;

        int[][] result = new int [m][n];

        for(int i = 0; i<m; i++)
            for(int j = 0;j<n;j++)
                result[i][j] = nextgeneration1(board,m,n,i,j);
        return result;
    }

    private int nextgeneration1(int[][] board, int MAXROW, int MAXCOL, int row, int col) {
        
        int count =0;
        int result = 1;
         for(int r = row-1; r <= row+1; r++)  
                for(int c = col-1; c <= col+1; c++) {  
                    if(r < 0 || r >= MAXROW || c < 0 || c >= MAXCOL)  
                        continue;  
                    if(r==row && c == col)
                        continue;
                    if(board[r][c] == 1)  
                        count++;  
                }  
         if(count==3)
             result = 1;
         else if(board[row][col] == 1 && count ==2)
             result = 1;
         else 
             result = 0;
        
        return result;
    }
}

思路2
要求inplace解法,即不用额外的空间,那么就要同时保存细胞 前后的状态
这个解法用0,1,2,3来表示细胞下一代的计算结果,计算下一代时(统计邻居和计算下一个状态),把这四种情况都考虑进去,
最后矩阵%2得到最终结果。
0: 0->0
1: 1->1
2: 1->0
3: 0->1

复杂度
空间(1),时间(M*N)

实现代码2

public class GameofLife {
    /**
     *     0 : 上一轮是0,这一轮过后还是0
        1 : 上一轮是1,这一轮过后还是1
        2 : 上一轮是1,这一轮过后变为0
        3 : 上一轮是0,这一轮过后变为1
     * @param board
     * @return
     */
    public int[][] Solution2(int[][] board){
        int m = board.length;

        int n = board[0].length;

        int[][] result = new int [m][n];

        for(int i = 0; i<m; i++)
            for(int j = 0;j<n;j++)
                result[i][j] = nextgeneration2(board,m,n,i,j);
        
        for(int i = 0; i<m; i++)
            for(int j = 0;j<n;j++)
                result[i][j] =     result[i][j] % 2;
        
        return result;
    }

    private int nextgeneration2(int[][] board, int MAXROW, int MAXCOL, int row, int col) {
        
        int count =0;
        int result = 1;
         for(int r = row-1; r <= row+1; r++)  
                for(int c = col-1; c <= col+1; c++) {  
                    if(r < 0 || r >= MAXROW || c < 0 || c >= MAXCOL)  
                        continue;  
                    if(r==row && c == col)
                        continue;
                    if(board[r][c] == 1 || board[r][c] == 2)  
                        count++;  
                }  
         
         if(board[row][col] == 1 && (count ==2 || count ==3))
             result = 2;
         else if  (board[row][col]==0 && count == 3) 
             result = 3;
         else
             result = board[row][col];
        
        return result;
    }
}

测试代码

public class GameofLifeTest {

    private GameofLife s;
    
    @Before
        public void setUp() {
         s = new GameofLife();
        }
     
    @Test
    public void testSolution1() {
        
        int[][] nums = {
                {1,0,1},
                {1,0,1},
                {1,0,1}
        };
        int[][] expect = {
                {1,0,1},
                {1,0,1},
                {1,0,1}
        };
        
        int[][] result = s.Solution1(nums);
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++)
                System.out.print(result[i][j]);
            System.out.println("");
        }        
    }
    
    @Test
    public void testSolution2() {
        
        int[][] nums = {
                {1,0,1},
                {1,0,1},
                {1,0,1}
        };
        int[][] expect = {
                {1,0,1},
                {1,0,1},
                {1,0,1}
        };
        
        int[][] result = s.Solution2(nums);
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++)
                System.out.print(result[i][j]);
            System.out.println("");
        }        
    }
    
}

测试结果

000
101
000

101
000
101

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值