zoukankan      html  css  js  c++  java
  • 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.

    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?

    链接: http://leetcode.com/problems/game-of-life/

    题解:

    生命游戏。题目比较长,用extra array做的话比较简单,但要求in-place的话,我们就要使用一些技巧。这里的方法来自yavinci,他的很多Java解法都既精妙又易读,真的很厉害。 我们用两个bit位来代表当前回合和下回合的board。

    00代表当前dead

    01代表当前live, next dead

    10代表当前dead,next live

    11代表当前和next都是live

    按照题意对当前cell进行更新,全部更新完毕以后, 需要再遍历一遍整个数组,将board upgrade到下一回合, 就是每个cell >>= 1。

    Time Complexity - O(mn), Space Complexity - O(1)。

    public class Solution {
        public void gameOfLife(int[][] board) {           
            if(board == null || board.length == 0) {
                return;
            }
            
            for(int i = 0; i < board.length; i++) {
                for(int j = 0; j < board[0].length; j++) {
                    int liveNeighbors = getLiveNeighbors(board, i, j);
                    if((board[i][j] & 1) == 1) {
                        if(liveNeighbors >= 2 && liveNeighbors <= 3) {
                            board[i][j] = 3;             // change to "11", still live
                        }                                // else it stays as "01", which will be eleminated next upgrade
                    } else {
                        if(liveNeighbors == 3) {
                            board[i][j] = 2;     // change to "10", become live
                        }
                    }
                }
            }
            
            for(int i = 0; i < board.length; i++) {
                for(int j = 0; j < board[0].length; j++) {
                    board[i][j] >>= 1;
                }
            }
        }
        
        private int getLiveNeighbors(int[][] board, int row, int col) {
            int res = 0;
            for(int i = Math.max(row - 1, 0); i <= Math.min(board.length - 1, row + 1); i++) {
                for(int j = Math.max(col - 1, 0); j <= Math.min(board[0].length - 1, col + 1); j++) {
                    res += board[i][j] & 1;
                }
            }
            res -= board[row][col] & 1;
            return res;
        }
    }

    二刷:

    稍微简写了一下。

    Java:

    public class Solution {
        private int[][] directions = new int[][] {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, 0}, {1, -1}, {1, 1}};
        
        public void gameOfLife(int[][] board) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    int sum = 0;
                    for (int[] direction : directions) {
                        int row = i + direction[0];
                        int col = j + direction[1];
                        if (row < 0 || col < 0 || row > board.length - 1 || col > board[0].length - 1) {
                            continue;
                        }
                        if ((board[row][col] & 1) == 1) {
                            sum++;
                        }
                    }
                    if (board[i][j] == 1 && (sum == 2 || sum == 3)) {
                        board[i][j] = 3;
                    } else if (sum == 3) {
                        board[i][j] = 2;     // 10
                    }
                }
            }
            
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    board[i][j] >>= 1;
                }
            }
        }
    }

    三刷:

    和上述一样的方法,就是写。

    Java:

    public class Solution {
        public void gameOfLife(int[][] board) {
            if (board == null || board.length == 0) return;
            int rowNum = board.length, colNum = board[0].length; 
            
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    int count = getNeighborLiveCells(board, i, j);
                    if (board[i][j] == 1) {
                        if (count == 2 || count == 3) board[i][j] = 3;
                    } else {
                        if (count == 3) board[i][j] = 2;
                    }
                }
            }
            
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    board[i][j] >>= 1;
                }
            }
        }
        
        private int getNeighborLiveCells(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 < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1|| (i == row && j == col)) continue;
                    if ((board[i][j] & 1) == 1) count++;
                }
            }
            return count;
        }
    }

    Reference:

    https://leetcode.com/discuss/68352/easiest-java-solution-with-explanation

    https://leetcode.com/discuss/61912/c-o-1-space-o-mn-time

    https://leetcode.com/discuss/61910/clean-o-1-space-o-mn-time-java-solution

  • 相关阅读:
    JavaScript高级程序设计之动态脚本及动态样式
    JavaScript高级程序设计之location对象
    JavaScript高级程序设计之window对象
    JavaScript高级程序设计之寄生组合式继承
    JavaScript高级程序设计之原型对象
    编写可维护的JavaScript之简易模版
    编写可维护的JavaScript之事件处理
    JavaScript 编码风格指南
    JavaScript高级程序设计之基本包装类型
    JavaScript高级程序设计之函数
  • 原文地址:https://www.cnblogs.com/yrbbest/p/5040751.html
Copyright © 2011-2022 走看看