zoukankan      html  css  js  c++  java
  • Leet Code 289.生命游戏

    题目

    (来自LeetCode)

    给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

    如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
    如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
    如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
    如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
    根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。

    思路

    重要的是要对周围8个位置进行判断其细胞死活。这个操作可以定义一个数组,通过8次循环,来达到对8个位置的操作。

    int[][] go = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
    for (int k = 0; k < 8; k++) {
                if( (i + go[k][0]) >= 0 && (i + go[k][0]) < board.length && (j + go[k][1]) >= 0 && (j + go[k][1]) < board[0].length ) {
                    sum = (board[i + go[k][0]][j + go[k][1]] & 1) == 1 ? sum + 1 : sum;
                }
            }
    

    第二个难点,是根据周围细胞死活数量,对自身状态的改变。共有四条判断。

    解法一

    可以另外创建一个 m × n的矩阵,记录细胞的初始状态,然后更新原矩阵状态。但是这样的空间复杂度很高。

    解法二

    根据其中的题解,有一个思路很厉害。每一个细胞有上一个状态和下一个状态,而每个状态有死和活,也就是一个细胞可以有4种可能性。我们假定一个细胞的状态是(下一个状态,上一个状态)。那么我们可以用,00,01,10,11来表示四种状态。即通过0,1,2,3来表示。

    • 00表示下一个状态死,上一个状态死
    • 01表示下一个状态死,上一个状态活
    • 10表示下一个状态活,上一个状态死
    • 11表示下一个状态活,上一个状态活

    我们通过与01与运算,可以得出是否细胞上一个状态是活,计算得到周围的活细胞数目。

    然后根据数目,对细胞状态进行改变。赋予相应的值0,1,2,3。最后将整个数组向右移一位,得到所有细胞的下一个状态。

    原先我的想法是用(上一个状态,下一个状态)来表示,但是这就会造成非常不一样的结果。

    代码

    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++) {
                    board[i][j] = new_board(board, i, j);
                }
            }
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    board[i][j] >>= 1;
                }
            }
        }
        public int new_board(int[][] board, int i, int j) {
            int sum = 0;
            int[][] go = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
            for (int k = 0; k < 8; k++) {
                if( (i + go[k][0]) >= 0 && (i + go[k][0]) < board.length && (j + go[k][1]) >= 0 && (j + go[k][1]) < board[0].length ) {
                    sum = (board[i + go[k][0]][j + go[k][1]] & 1) == 1 ? sum + 1 : sum;
                }
            }
            if(board[i][j] == 1 && sum < 2) board[i][j] = 1;
            else if(board[i][j] == 1 && (sum == 2 || sum == 3)) board[i][j] = 3; 
            else if(board[i][j] == 1 && sum > 3) board[i][j] = 1;
            if (board[i][j] == 0 && sum == 3) board[i][j] = 2;
            return board[i][j];
        }
    }
    
  • 相关阅读:
    超级强大的SVG SMIL animation动画详解
    Java Math的 floor,round和ceil的总结
    理解SVG的viewport,viewBox,preserveAspectRatio
    SVG-1
    PHP通过exec执行git pull
    Nodejs中request出现ESOCKETTIMEDOUT解决方案
    Linux安装了mysql 无法远程连接
    linux下docker启动nginx无法访问80端口
    ZPL文件打印
    k8s结合helm部署
  • 原文地址:https://www.cnblogs.com/chenshaowei/p/13186258.html
Copyright © 2011-2022 走看看