289 生命游戏(模拟、二进制)

1. 问题描述:

根据百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。

示例 1:

输入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
输出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]

输入:board = [[1,1],[1,0]]
输出:[[1,1],[1,1]]

提示:
m == board.length
n == board[i].length
1 <= m, n <= 25
board[i][j] 为 0 或 1

进阶:
你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/game-of-life

2. 思路分析:

分析题目可以知道我们模拟整个过程即可,但是由于不能开额外的空间来存储结果,所以我们需要使用其他的方法。因为board存储的是32位二进制数字的一位,所以每个存储空间只是使用到了一位二进制数字,所以我们可以充分利用这个特点,遍历当前的矩阵board[i][j]周围的八个相邻的元素,计算出周围八个位置的活的细胞数目,根据当前位置周围八个位置活的细胞数目将当前boardp[i][j]值更新为题目说的对应的状态,因为第一位已经使用了所以我们需要将结果更新到board[i][j]对应二进制数字的第二位,更新的时候使用位运算的移位操作即可。最后需要再遍历一遍board列表,将二进制的第二位右移一位那么就是最终的答案了。

3. 代码如下:

from typing import List


class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        r, c = len(board), len(board[0])
        if r == 0 or c == 0: return
        for i in range(r):
            for j in range(c):
                live = 0
                for m in range(max(0, i - 1), min(r, i + 2)):
                    for n in range(max(0, j - 1), min(c, j + 2)):
                        # 这里需要排除掉当前自己的位置
                        if (m != i or n != j) and board[m][n] & 1:
                            live += 1
                cur, next = board[i][j] & 1, 0
                if cur:
                    if live < 2 or live > 3:
                        next = 0
                    else:
                        next = 1
                else:
                    if live == 3:
                        next = 1
                    else:
                        next = 0
                board[i][j] |= (next << 1)
        # 更新列表的状态
        for m in range(r):
            for n in range(c):
                board[m][n] >>= 1

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值