zoukankan      html  css  js  c++  java
  • 0289. Game of Life (M)

    Game of Life (M)

    题目

    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?

    题意

    细胞游戏:一个细胞有生死两种状态,如果一个细胞周围活着的细胞个数小于2或大于3,则该细胞死亡;若个数为2,则状态不变;若个数为3,则该细胞生还。给定某一个时刻的细胞状态数组,要求返回下一时刻的细胞状态数组。

    思路

    题目要求状态的变化是同时进行的,因此不能先计算出一个细胞的状态,再用这个更新后的状态去计算其他细胞的状态,且要求仅在原数组上进行修改。

    最简单的方法是直接将原数组复制一份,每次查询邻接生存细胞个数都以这个拷贝数组为基准。

    原地修改方法:扩展数组中的值类型如下:
    0 -- dead -> dead
    1 -- live -> live
    2 -- dead -> live
    3 -- live -> dead
    第一次遍历,将数组中的值按要求修改为扩展值,第二次遍历再将修改完的扩展值改回0和1。


    代码实现

    Java

    拷贝

    class Solution {
        public void gameOfLife(int[][] board) {
            int m = board.length, n = board[0].length;
            int[][] copy = new int[m][];
            for (int i = 0; i < m; i++) {
                copy[i] = Arrays.copyOf(board[i], n);
            }
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    int count = count(copy, i, j, m, n);
                    if (count < 2 || count > 3) {
                        board[i][j] = 0;
                    } else if (count == 3) {
                        board[i][j] = 1;
                    }
                }
            }
        }
    
        private int count(int[][] board, int i, int j, int m, int n) {
            int[] diff = { -1, 0, 1 };
            int count = 0;
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 3; y++) {
                    int nextI = i + diff[x], nextJ = j + diff[y];
                    if (!(x == 1 && y == 1) && isValid(nextI, nextJ, m, n) && board[nextI][nextJ] == 1) {
                        count++;
                    }
                }
            }
            return count;
        }
    
        private boolean isValid(int i, int j, int m, int n) {
            return i >= 0 && i < m && j >= 0 && j < n;
        }
    }
    

    原地

    class Solution {
        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 count = count(board, i, j, m, n);
                    int origin = board[i][j];
                    if (count < 2 || count > 3) {
                        board[i][j] = origin == 0 ? 0 : 3;
                    } else if (count == 3) {
                        board[i][j] = origin == 0 ? 2 : 1;
                    }
                }
            }
    
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    int value = board[i][j];
                    board[i][j] = value == 3 ? 0 : value == 2 ? 1 : value;
                }
            }
        }
    
        private int count(int[][] board, int i, int j, int m, int n) {
            int[] diff = { -1, 0, 1 };
            int count = 0;
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 3; y++) {
                    int nextI = i + diff[x], nextJ = j + diff[y];
                    if (!(x == 1 && y == 1) && isValid(nextI, nextJ, m, n) && board[nextI][nextJ] % 2 == 1) {
                        count++;
                    }
                }
            }
            return count;
        }
    
        private boolean isValid(int i, int j, int m, int n) {
            return i >= 0 && i < m && j >= 0 && j < n;
        }
    
        public static void main(String[] args) {
            Solution s = new Solution();
            s.gameOfLife(new int[][] { { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 }, { 0, 0, 0 } });
        }
    }
    
  • 相关阅读:
    五分钟完成 ABP vNext 通讯录 App 开发
    .NET Conf: Xamarin专场会议3.23 开幕
    2020 年 中国.NET开发者调查报告
    推荐一个很棒的开源工作流elsa-core
    尝试使用 Visual Studio Online (Cloud IDE)
    Mongo2Go 介绍
    DevExpress作为企业赞助商加入.NET基金会
    【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发
    云原生时代 来看看十年前李彦宏、马化腾和马云对云计算的评价
    .NET 在云原生时代的蜕变,让我在云时代脱颖而出
  • 原文地址:https://www.cnblogs.com/mapoos/p/13193742.html
Copyright © 2011-2022 走看看