289. Game of Life

来源:互联网 发布:js左右拖动滑块插件 编辑:程序博客网 时间:2024/06/05 17:32

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.

  1. 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
起初我以为这道题目的难度在于将题目翻译成中文,哈哈,英文不好有时会导致理解题意有偏差,最初采用一种最常规的方式,既然需要最后一次性更新数组,那么一种可行的方式是利用另外一个数组来保存结果,我没有用到什么华丽的算法技巧,只是按照题目意思逐渐做出来,代码如下:
public void gameOfLife(int[][] board) {
        // 特殊情况处理
        if(board == null || board.length == 0 || board[0].length == 0){
            return;
        }
        
        int row = board.length;
        int col = board[0].length;
        int[][] updateBoard = new int[row][col];
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                // 对于每一个元素,搜索存活的元素的数目
                int num = liveNeighbor(board, i, j);
                // 接下来是按条件判断
                if(board[i][j] == 1){
                    if(num < 2){
                        updateBoard[i][j] = 0;
                    }else if(num == 2 || num == 3){
                        updateBoard[i][j] = 1;
                    }else{
                        updateBoard[i][j] = 0;
                    }
                }else{
                    if(num == 3){
                        updateBoard[i][j] = 1;
                    }
                }
            }
        }
        
        // 最后是更新数组元素值
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                board[i][j] = updateBoard[i][j];
            }
        }
    }
    
    private int liveNeighbor(int[][] board, int row, int col){
        int count = 0;
        for(int i = row - 1; i <= row + 1; i++){
            for(int j = col - 1; j <= col + 1; j++){
                if(i == row && j == col){
                    continue;
                }
                if(i >= 0 && i < board.length && j >= 0 && j < board[0].length &&  board[i][j] == 1){
                    count++;
                }
            }
        }
        
        return count;
    }
这道题目的follow up中提出使用inplace的方式,我个人理解就是in place方式就是不让我们自己再次开辟一个数组用来存储结果,我自己没有想到好的解决方案,参考了别人的解决方案实现了以下,过程解释如下:
为了使用in place的方式解决问题,使用两位存储两种状态
-00 dead(next) <-- dead (current)
-01 dead(next) <-- live(current)
-10 live(next) <-- dead(current)
-11 live(next) <-- live(current)

在一开始,每一个单元要么是00 或者是01

注意第一个状态是依赖于第二个状态

为了得到当前状态,只需要进行 board[i][j] & 1

为了得到下一个状态,只需要进行 board[i][j] >> 1

代码如下:

 public void gameOfLife(int[][] board) {
       // 特殊情况处理
       if(board == null || board.length == 0 || board[0].length == 0){
           return;
       }
       
       int row = board.length;
       int col = board[0].length;
       for(int i = 0; i < row; i++){
           for(int j = 0; j < col; j++){
               int count = liveNeighbor(board, row, col, i, j);
               if(count == 2 || count == 3){
                    if(board[i][j] == 1){
                        board[i][j] = 3;
                    }
               }
               if(board[i][j] == 0 && count == 3){
                   board[i][j] = 2;
               }
           }
       }
       
       for(int i = 0; i < row; i++){
           for(int j = 0; j < col; j++){
                board[i][j] = board[i][j] >> 1;   
           }
       }
    }
    
    private int liveNeighbor(int[][] board, int row, int col, int i, int j){
        int count = 0;
        for(int p = i - 1; p <=i + 1; p++){
            for(int q = j - 1; q <= j + 1; q++){
                if(p == i && q == j){
                    continue;
                }
                if(p >= 0 && p < row && q >= 0 && q < col && (board[p][q] & 1) == 1){
                    count++;
                }
            }
        }
        return count;
    }

0 0
原创粉丝点击