Game of Life

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):

  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.

  2. Any live cell with two or three live neighbors lives on to the next generation.

  3. Any live cell with more than three live neighbors dies, as if by over-population..

  4. 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:

  1. 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.

  2. 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?

分析

这道题方法比较直接,直接遍历找live及dead的neighbors数量,然后更新矩阵即可。关键是如何保存之前状态,我们可以暴力的直接新建一个矩阵来作修改或者用两位int来暂时存原来状态及更新后的状态,高位表示下一步状态,低位表示原先状态,然后最后更新完后再遍历矩阵根据高位来把矩阵更新到最新状态。

往往这道题的follow up会围绕board的存储来展开,因为根本没必要用int来表示状态,太耗空间。最优存储方法是不用二维矩阵来表示,而是存所有live点的坐标。更新的方法就是扫一遍已存在的live点,扫其邻居,对其邻居而言,每被扫一次,次数加1, 用一个Map记录邻居及邻居被扫的次数,这些邻居最后会可能成为新的live点,最后根据Map里的value来确定新的live点。

复杂度

time: O(MN), space: O(1)

代码

public class Solution {
    //00 dead -> dead
    //10 dead -> live
    //01 live -> dead
    //11 live -> live
    public void gameOfLife(int[][] board) {
        int rows = board.length;
        if (rows == 0) 
            return;
        int cols = board[0].length;
        
        // 定义邻居的方向
        int[][] dirs = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                // 记录活邻居的数量
                int liveCount = 0;
                for (int k = 0; k < dirs.length; k++) {
                    int x = i + dirs[k][0];
                    int y = j + dirs[k][1];
                    if (x >= 0 && x < rows && y >= 0 && y < cols) {
                        // 根据低位数字得到旧状态
                        if (board[x][y] % 2 == 1) 
                            liveCount++;
                    }
                }
                
                if (board[i][j] % 2 == 1) {
                    if (liveCount == 2 || liveCount == 3) 
                        board[i][j] += 2;
                } else {
                    if (liveCount == 3) 
                        board[i][j] += 2;
                }
            }
        }
        
        // 根据高位更新矩阵到最新状态
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                board[i][j] >>= 1;
            }
        }
    }
}

微斯渝
39 声望15 粉丝