LeetCode289. 生命遊戲

1.題目

根據 百度百科 ,生命遊戲,簡稱爲生命,是英國數學家約翰·何頓·康威在 1970 年發明的細胞自動機。

給定一個包含 m × n 個格子的面板,每一個格子都可以看成是一個細胞。每個細胞都具有一個初始狀態:1 即爲活細胞(live),或 0 即爲死細胞(dead)。每個細胞與其八個相鄰位置(水平,垂直,對角線)的細胞都遵循以下四條生存定律:

如果活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡;
如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;
如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡;
如果死細胞周圍正好有三個活細胞,則該位置死細胞復活;
根據當前狀態,寫一個函數來計算面板上所有細胞的下一個(一次更新後的)狀態。下一個狀態是通過將上述規則同時應用於當前狀態下的每個細胞所形成的,其中細胞的出生和死亡是同時發生的。

輸入:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
輸出:
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]

進階:
你可以使用原地算法解決本題嗎?請注意,面板上所有格子需要同時被更新:你不能先更新某些格子,然後使用它們的更新後的值再更新其他格子。
本題中,我們使用二維數組來表示面板。原則上,面板是無限的,但當活細胞侵佔了面板邊界時會造成問題。你將如何解決這些問題?

2.1 記錄每個需要變化的細胞的位置

對於每個細胞遍歷其周圍八個細胞,記錄活細胞的數量,然後判斷其是否需要變化,如果需要則放入list中。

class Solution {
public:
    int dx[8] = {-1,-1,-1,0,0,1,1,1};
    int dy[8] = {-1,0,1,-1,1,-1,0,1};
    int findAlive(vector<vector<int>>& board, int x, int y){
        int res = 0;
        for(int i = 0; i < 8; i++){
            auto cx = x + dx[i], cy = y + dy[i];
            if(cx >= 0 && cx < board.size() && cy >= 0 && cy < board[0].size() && board[cx][cy] == 1)
                res++;
        }
        return res;
    }
    struct node{
        int x,y;
        node(int x_, int y_) : x(x_), y(y_){}
    };
    void gameOfLife(vector<vector<int>>& board) {
        list<node> Set;
        int m = board.size();
        if(m <= 0) return;
        int n = board[0].size();
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                int cnt = 0;
                cnt = findAlive(board, i, j);
                if(board[i][j] == 1){
                    if(cnt < 2 || cnt > 3){
                        Set.push_back(node(i,j));
                    }
                }
                else{
                    if(cnt == 3) Set.push_back(node(i,j));
                }
            }
        }
        for(auto& it : Set){
            board[it.x][it.y] = 1 - board[it.x][it.y];
        }
    }
};

2.2 原地算法

將需要變化的活細胞標記爲2,將需要變化的死細胞標記爲-1.
遍歷兩遍數組。

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                int count = 0;
                if(i-1 >= 0 && j-1>=0 && board[i-1][j-1]>0) count++;
                if(i-1 >= 0 && board[i-1][j]>0) count++;
                if(i-1 >= 0 && j+1 < n && board[i-1][j+1]>0) count++;
                if(j-1 >= 0 && board[i][j-1] > 0) count++;
                if(j+1 < n && board[i][j+1] > 0) count++;
                if(i+1 < m && j-1>=0 && board[i+1][j-1] > 0) count++;
                if(i+1 < m && board[i+1][j] > 0) count++;
                if(i+1 < m && j+1<n && board[i+1][j+1] > 0) count++;
                
                if(board[i][j] > 0){
                    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;}
            }
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章