[leetcode/lintcode 题解] 算法面试高频题详解:生命游戏

简介: [leetcode/lintcode 题解] 算法面试高频题详解:生命游戏

描述
根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞具有一个初始状态 live(1)即为活细胞, 或 dead(0)即为死细胞。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

  1. 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
  2. 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
  3. 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
  4. 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

根据当前状态,写一个函数来计算面板上细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。

在线评测地址:领扣题库官网

样例1
输入: 
[
  [0,1,0],
  [0,0,1],
  [1,1,1],
  [0,0,0]
]
输出: 
[
  [0,0,0],
  [1,0,1],
  [0,1,1],
  [0,1,0]
]
  1. 你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
  2. 本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?

解题思路
原地完成更新的方法:
我们用32位整数的最后两位二进制来表示boardi的当前状态以及下一状态,0 表示死细胞,1 表示活细胞。由于初始时board由 0 和 1 构成,所以我们设定最低位的二进制表示当前细胞的状态,倒数第二位二进制表示下一状态,不同的表示对应的结果如下:

  • 00 -- 当前为死细胞且下一状态仍为死细胞
  • 01 -- 当前为活细胞且下一状态为死细胞
  • 10 -- 当前为死细胞且下一状态为活细胞
  • 11 -- 当前为活细胞且下一状态仍为活细胞

对于前两种情况我们不需要做改动,因为给出的board内所有元素的倒数第二位均为0,所以需要修改的为后两种情况:
当死细胞周围正好有 3 个活细胞时,则满足第三种状态,所以需要重新赋值:boardi = 2
当活细胞周围正好有 2 个或者 3 个活细胞时,则满足第四种状态,所以需要重新赋值:boardi = 3

源代码

class Solution:
    """
    @param board: the given board
    @return: nothing
    """
    def gameOfLife(self, board):
        # Write your code here
        m = len(board)
        n = len(board[0])
    
        for i in range(m):
            for j in range(n):
                # 计算与board[i][j]相邻的活细胞数量
                lives = self.liveNeighbors(board, m, n, i, j);
                
                # 如果当前位置为活细胞,且相邻活细胞数量为2个或者3个,则下一状态仍为活细胞
                if board[i][j] == 1 and lives >= 2 and lives <= 3:  
                    board[i][j] = 3
                
                # 如果当前位置为死细胞,且相邻活细胞数量为3个,则下一状态为活细胞
                if board[i][j] == 0 and lives == 3:
                    board[i][j] = 2
        
        # 更新细胞状态
        for i in range(m):
            for j in range(n):
                board[i][j] >>= 1
    
    def liveNeighbors(self, board, m, n, i, j):
        lives = 0
        for x in range(max(i - 1, 0), min(i + 1, m - 1) + 1):
            for y in range(max(j - 1, 0), min(j + 1, n - 1) + 1):
                lives += board[x][y] & 1
        lives -= board[i][j] & 1
        return lives

更多题解参考:九章官网solution

相关文章
|
1月前
|
存储 算法 编译器
米哈游面试算法题:有效的括号
米哈游面试算法题:有效的括号
27 0
|
1月前
|
负载均衡 算法 应用服务中间件
面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
字节跳动面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
42 0
|
8天前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
19 0
|
14天前
|
存储 缓存 算法
面试遇到算法题:实现LRU缓存
V哥的这个实现的关键在于维护一个双向链表,它可以帮助我们快速地访问、更新和删除最近最少使用的节点,同时使用哈希表来提供快速的查找能力。这样,我们就可以在 O(1) 的时间复杂度内完成所有的缓存操作。哈哈干净利索,回答完毕。
|
25天前
|
算法
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
21 3
|
25天前
|
存储 算法
代码随想录算法训练营第五十九天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
代码随想录算法训练营第五十九天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
22 1
|
25天前
|
算法
代码随想录算法训练营第五十七天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
代码随想录算法训练营第五十七天 | LeetCode 739. 每日温度、496. 下一个更大元素 I
18 3
|
25天前
|
算法
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
34 1
|
25天前
|
算法
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
24 1
|
26天前
|
算法 API DataX
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”