289. 生命游戏

根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。

给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是 同时 发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。
给定当前 board 的状态,更新 board 到下一个状态。
注意 你不需要返回任何东西。
示例 1:
在这里插入图片描述
输入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
输出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]

C++

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        int x_index[]={-1,0,1,-1,1,-1,0,1};
        int y_index[]={-1,-1,-1,0,0,1,1,1};
        int rows=board.size();
        int cols=board[0].size();
        
        for( int i=0;i<rows;i++ ){
            for( int j=0;j<cols;j++ ){
                int sum=0;
                for( int k=0;k<8;k++ ){
                    //确定当前矩阵中i,j元素周围8个位置的x,y坐标
                    int x=i+x_index[k];
                    int y=j+y_index[k];
                    if( x>=0 && x<rows && y>=0 && y<cols ){
                        //如果当前坐标为有效坐标
                        //原矩阵对应坐标的值为0(死亡)的情况:与运算(一假则假)
                        // 0 0
                        // 0 1
                        // 0 0
                        //原矩阵对应坐标的值为1(存活)的情况:与运算(一假则假)
                        // 0 1
                        // 0 1
                        // 0 1
                        sum+=(board[x][y]&1);//对当前坐标为i,j周围8个坐标元素值为1(存活)的进行求和
                    }
                }
                if( 1==board[i][j] ){
                    //当前坐标为i,j的元素值为1(存活)
                    if( 2==sum || 3==sum ){
                        //对当前坐标为i,j周围8个坐标元素值为1(存活)的总数为2个或者3个,依据规则当前元素存活
                        // 或运算(一真则真)
                        // 0 1
                        // 1 0
                        // 1 1
                        // 此时当前坐标为i,j的值为3
                        board[i][j] |=2;
                    }
                }else{
                    //当前坐标为i,j的元素值为0(死亡)
                    if( 3==sum ){
                        //对当前坐标为i,j周围8个坐标元素值为1(存活)的总数刚好为3个,则该位置死细胞复活
                        // 或运算(一真则真)
                        // 0 0
                        // 1 0
                        // 1 0
                        // 此时当前坐标为i,j的值为2
                        board[i][j] |=2;
                    }
                }
            }
        }
        for( int i=0;i<rows;i++ ){
            for( int j=0;j<cols;j++ ){
                //经上述处理后,矩阵汇总元素的值有四种情况(0(0 0),1(0 1),2(1 0)(存活),3(1 1)(存活))
                //位运算 右移 每向右移动一位相当于除以2
                //0:
                // 0 0
                // 0 0
                //右移一位结果为:0
                //1:
                // 0 1
                // 0 0
                //右移一位结果为:0
                //2:
                // 1 0
                // 0 1
                //右移一位结果为:1
                //3:
                // 1 1
                // 0 1
                //右移一位结果为:1
                board[i][j]>>=1;
            }
        }
    }
    
};

时间复杂度

O ( M ∗ N ) O(M*N) O(MN)

空间复杂度

O ( 1 ) O(1) O(1)

Java

class Solution {
    public void gameOfLife(int[][] board) {
        int x_index []={-1,0,1,-1,1,-1,0,1};
        int y_index []={-1,-1,-1,0,0,1,1,1};
        int rows=board.length;
        int cols=board[0].length;
        for( int i=0;i<rows;i++ ){
            for( int j=0;j<cols;j++ ){
                int sum=0;
                for( int k=0;k<8;k++ ){
                    int x=i+x_index[k];
                    int y=j+y_index[k];
                    if( x>=0 && x<rows && y>=0 && y<cols ){
                        sum+=(board[x][y]&1);
                    }
                }
            
                if( 1==board[i][j] ){
                    if( 2==sum || 3==sum ){
                        board[i][j]|=2;
                    }
                }else{
                    if( 3==sum ){
                        board[i][j]|=2;
                    }
                }
            }
        }
        for( int i=0;i<rows;i++ ){
            for( int j=0;j<cols;j++ ){
                 board[i][j]>>=1;
            }
        }
    }
}

时间复杂度

O ( M ∗ N ) O(M*N) O(MN)

空间复杂度

O ( 1 ) O(1) O(1)

Python

class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        x_index=[-1,0,1,-1,1,-1,0,1];
        y_index=[-1,-1,-1,0,0,1,1,1];
        rows=len(board);
        cols=len(board[0]);
        for i in range(rows):
            for j in range(cols):
                sum=0;
                for k in range(8):
                    x=i+x_index[k];
                    y=j+y_index[k];
                    if x>=0 and x<rows and y>=0 and y<cols:
                        sum=sum +(1 & board[x][y]);
                if 1==board[i][j]:
                    if 2==sum or 3==sum:
                        board[i][j]=board[i][j]|2;
                else:
                    if 3==sum:
                        board[i][j]=board[i][j]|2;
        for i in range(rows):
            for j in range(cols):
                board[i][j]=board[i][j]>>1;

时间复杂度

O ( M ∗ N ) O(M*N) O(MN)

空间复杂度

O ( 1 ) O(1) O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值