細胞生死問題 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."this

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

Follow upthree

  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?

解決:遊戲

【題意】 ip

這道題是有名的康威生命遊戲, 這是一種細胞自動機,每個位置有兩種狀態,1爲活細胞,0爲死細胞,對於每一個位置都知足以下的條件:ci

1. 若是活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡;get

2. 若是活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;it

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

4. 若是死細胞周圍正好有三個活細胞,則該位置死細胞復活;

題目要求咱們用置換方法in-place來解題,因此咱們就不能新建一個相同大小的數組,那麼咱們只能更新原有數組,可是題目中要求全部的位置必須被同時更新,可是在循環程序中咱們仍是一個位置一個位置更新的,那麼當一個位置更新了,這個位置成爲其餘位置的neighbor時,咱們怎麼知道其未更新的狀態呢,咱們能夠使用狀態機轉換:

狀態0(00): 死細胞轉爲死細胞

狀態1(01): 活細胞轉爲活細胞

狀態2(10): 活細胞轉爲死細胞

狀態3(11): 死細胞轉爲活細胞

咱們將全部狀態對2取餘,那麼狀態0和2就變成死細胞,狀態1和3就是活細胞,達成目的。

① 直接實現上面的解法。

 class Solution{ //0ms
    public void gameOfLife(int[][] board){
        int m = board.length;
        int n = board[0].length;
        for (int i = 0;i < m;i ++){
            for (int j = 0;j < n;j ++){
                int lives = 0;
                if (i > 0){//判斷上邊
                    lives += board[i - 1][j] == 1 || board[i - 1][j] == 2 ? 1 : 0;//狀態1,2初始爲活細胞
                }
                if (j > 0){//判斷左邊
                    lives += board[i][j - 1] == 1 || board[i][j - 1] == 2 ? 1 : 0;
                }
                if (i < m - 1){//判斷下邊
                    lives += board[i + 1][j] == 1 || board[i + 1][j] == 2 ? 1 : 0;
                }
                if (j < n - 1){//判斷右邊
                    lives += board[i][j + 1] == 1 || board[i][j + 1] == 2 ? 1 : 0;
                }
                if (i > 0 && j > 0){//判斷左上角
                    lives += board[i - 1][j - 1] == 1 || board[i - 1][j - 1] == 2 ? 1 : 0;
                }
                if (i < m - 1 && j < n - 1){//判斷右下角
                    lives += board[i + 1][j + 1] == 1 || board[i + 1][j + 1] == 2 ? 1 : 0;
                }
                if (i > 0 && j < n - 1){//判斷右上角
                    lives += board[i - 1][j + 1] == 1 || board[i - 1][j + 1] == 2 ? 1 : 0;
                }
                if (i < m - 1 && j > 0){//判斷左下角
                    lives += board[i + 1][j - 1] == 1 || board[i + 1][j - 1] == 2 ? 1 : 0;
                }
                if (board[i][j] == 0 && lives == 3){//死細胞轉換爲活細胞
                    board[i][j] = 3;
                }else if (board[i][j] == 1){//活細胞轉爲死細胞
                    if (lives < 2 || lives > 3) board[i][j] = 2;
                }
            }
        }
        //解碼
        for (int i = 0;i < m;i ++){
            for (int j = 0;j < n;j ++){
                board[i][j] = board[i][j] % 2;
            }
        }
    }
}

② 使用位操做進行編碼。

class Solution{ //1ms     public void gameOfLife(int[][] board){         int m = board.length, n = board[0].length;         for(int i = 0; i < m; i++){             for(int j = 0; j < n; j++){                 int lives = 0;                 // 累加上下左右及四個角還有自身的值                 for(int y = Math.max(i - 1, 0); y <= Math.min(i + 1, m - 1); y++){                     for(int x = Math.max(j - 1, 0); x <= Math.min(j + 1, n - 1); x++){                         // 累加bit1的值                         lives += board[y][x] & 1;                     }                 }                 // 若是本身是活的,周邊有兩個活的,lives是3                 // 若是本身是死的,周邊有三個活的,lives是3                 // 若是本身是活的,周邊有三個活的,lives減本身是3                 if(lives == 3 || lives - board[i][j] == 3){                     board[i][j] |= 2;                 }             }         }         // 右移就是新的值         for(int i = 0; i < m; i++){             for(int j = 0; j < n; j++){                 board[i][j] >>>= 1;             }         }     } }

相關文章
相關標籤/搜索