[LeetCode] 289. 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. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously.

Example:

Input: 
[
  [0,1,0],
  [0,0,1],
  [1,1,1],
  [0,0,0]
]
Output: 
[   [0,0,0],   [1,0,1],   [0,1,1],   [0,1,0] ] 

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?

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.

 

這道題是有名的 康威生命游戲, 而我又是第一次聽說這個東東,這是一種細胞自動機,每一個位置有兩種狀態,1為活細胞,0為死細胞,對於每個位置都滿足如下的條件:

1. 如果活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡

2. 如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活

3. 如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡

4. 如果死細胞周圍正好有三個活細胞,則該位置死細胞復活

由於題目中要求用置換方法 in-place 來解題,所以就不能新建一個相同大小的數組,那么只能更新原有數組,題目中要求所有的位置必須被同時更新,但在循環程序中還是一個位置一個位置更新的,當一個位置更新了,這個位置成為其他位置的 neighbor 時,怎么知道其未更新的狀態呢?可以使用狀態機轉換:

狀態0: 死細胞轉為死細胞

狀態1: 活細胞轉為活細胞

狀態2: 活細胞轉為死細胞

狀態3: 死細胞轉為活細胞

最后對所有狀態對2取余,則狀態0和2就變成死細胞,狀態1和3就是活細胞,達成目的。先對原數組進行逐個掃描,對於每一個位置,掃描其周圍八個位置,如果遇到狀態1或2,就計數器累加1,掃完8個鄰居,如果少於兩個活細胞或者大於三個活細胞,而且當前位置是活細胞的話,標記狀態2,如果正好有三個活細胞且當前是死細胞的話,標記狀態3。完成一遍掃描后再對數據掃描一遍,對2取余變成我們想要的結果。參見代碼如下:

 

class Solution {
public:
    void gameOfLife(vector<vector<int> >& board) {
        int m = board.size(), n = m ? board[0].size() : 0;
        vector<int> dx{-1, -1, -1, 0, 1, 1, 1, 0};
        vector<int> dy{-1, 0, 1, 1, 1, 0, -1, -1};
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int cnt = 0;
                for (int k = 0; k < 8; ++k) {
                    int x = i + dx[k], y = j + dy[k];
                    if (x >= 0 && x < m && y >= 0 && y < n && (board[x][y] == 1 || board[x][y] == 2)) {
                        ++cnt;
                    }
                }
                if (board[i][j] && (cnt < 2 || cnt > 3)) board[i][j] = 2;
                else if (!board[i][j] && cnt == 3) board[i][j] = 3;
            }
        }
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                board[i][j] %= 2;
            }
        }
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/289

 

類似題目:

Set Matrix Zeroes

 

參考資料:

https://leetcode.com/problems/game-of-life/

https://leetcode.com/problems/game-of-life/discuss/73217/Infinite-board-solution

https://leetcode.com/problems/game-of-life/discuss/73230/C%2B%2B-O(1)-space-O(mn)-time

https://leetcode.com/problems/game-of-life/discuss/73223/Easiest-JAVA-solution-with-explanation

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM