LeetCode/solutions/289. Game of Life.md
2019-11-07 20:47:51 +08:00

2.4 KiB
Raw Blame History

289. Game of Life

思路

给定一个二维数组每个元素代表一个细胞元素的值代表细胞当前的死活1为活细胞0为死细胞要求下一时刻所有细胞的死活状态。

细胞的下一个时刻的死活由如下条件决定:

  1. 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞下一时刻死亡;
  2. 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞下一时刻仍然存活;
  3. 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞下一时刻死亡;
  4. 如果死细胞周围正好有三个活细胞,则该位置死细胞下一时刻复活;

由于题目中要求in-place所以就不能新建一个相同大小的数组那么只能更新原有数组但是我们不能直接更新到下一时刻的状态 所以我们可以考虑更新到一个中间态,这个中间态可以随意定义,只要能区分开来就可以了,例子如下:

当前状态 下一状态 中间状态
情形一 0 0 0
情形二 0 1 -1
情形三 1 0 2
情形四 1 1 1

最后需要再遍历一遍把中间态改为最终态。

时间复杂度O(n)线性复杂度O(1)

C++

class Solution {
    const int dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
    const int dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
    int m, n;
private:
    int live_nbs(vector<vector<int>>& board, int i, int j){
        int count = 0, nx, ny;
        for(int k = 0; k < 8; k++){
            nx = i + dx[k];
            ny = j + dy[k];
            if(nx >= 0 && nx < m && ny >= 0 && ny < n && board[nx][ny] > 0)
                count++;
        }
        return count;
    }
public:
    void gameOfLife(vector<vector<int>>& board) {
        // 00 0, 01 -1, 10 2, 11 1 
        m = board.size();
        n = board[0].size();
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++){
                int count = live_nbs(board, i, j);
                if(board[i][j]){
                    if(count < 2 || count > 3) board[i][j] = 2;
                }
                else if(count == 3) board[i][j] = -1;
            }
        
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++){
                if(board[i][j] == 2) board[i][j] = 0;
                else if(board[i][j] == -1) board[i][j] = 1;
            }
    }
};