【面试经典150 | 矩阵】生命游戏

这篇具有很好参考价值的文章主要介绍了【面试经典150 | 矩阵】生命游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……

专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:

  • Tag:介绍本题牵涉到的知识点、数据结构;
  • 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
  • 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
  • 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
  • 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。

Tag

【矩阵】【数组】


题目来源

面试经典150 | 289. 生命游戏

【面试经典150 | 矩阵】生命游戏,面试经典150题,矩阵,数组,C++,算法

题目解读

根据一些四条生存规则来完成对网格面板的更新,并且更新是同时发生的。


解题思路

方法一: O ( m n ) O(mn) O(mn) 额外空间

八个方向

首先明确网格点的八个更新方向:左边、左上、正上、右上、右边、右下、正下、左下。我们可以嵌套枚举 dirs = [0, -1, 0] 来实现以上的八个方向。

四条生存准则

每个网格点代表一个细胞,每个细胞有一个状态,1 表示活细胞,0 表示死细胞,细胞的更新规则如下:

  • (1)活细胞周围八个方向位置上活细胞数小于两个,该位置细胞死亡;
  • (2)活细胞周围八个方向位置上的活细胞数等于两个或三个,该位置细胞仍然存活;
  • (3)活细胞周围八个方向位置上活细胞数超过三个,该位置细胞死亡;
  • (4)死细胞周围八个方向位置上活细胞数等于三个,该位置细胞复活;

枚举每一个网格上的细胞,如果是活细胞,那么按照规则(1)(2)(3)更新 board;如果是死细胞,按照规则(4)更新 board

但是,需要复制 board 得到 copyBoard,利用 copyBoard 来判断当前细胞的状态(死亡还是存活),更新最后的结果到 board 上。

实现代码

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        int dirs[] = {0, -1, 1};
        int rows = board.size();
        int cols = board[0].size();

        vector<vector<int>> copyBoard = board;
        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols; ++col) {
                int cnts = 0;   // 表示周围相邻的八个方向上活细胞的数量
                for (int i = 0; i < 3; ++i) {
                    for (int j = 0; j < 3; ++j) {
                        if (!(dirs[i] == 0 && dirs[j] == 0)) {
                            int nRow = row + dirs[i];
                            int nCol = col + dirs[j];

                            // 更新 cnts
                            if (nRow >= 0 && nRow < rows && nCol >= 0 && nCol < cols && copyBoard[nRow][nCol] == 1) cnts += 1;
                        }
                    }
                }
                // 规则(1)(3)
                if (copyBoard[row][col] == 1 && (cnts < 2 || cnts > 3)) 
                    board[row][col] = 0;
                // 规则(4)
                if (copyBoard[row][col] == 0 && cnts == 3)
                    board[row][col] = 1;
            }
        }
    }
};

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为数组 board 的行数, n n n 为数组 board 的列数。

空间复杂度: O ( m n ) O(mn) O(mn),额外空间是辅助数组 copyBoard 使用的空间。

方法二: O ( 1 ) O(1) O(1) 额外空间

在本题中,如果细胞的状态发生了变化,一共只有两种:

  • 细胞从存活的状态转变成死亡的状态;
  • 细胞从死亡的状态转变成存活的状态。

于是,我们可以在按照规则进行判断时,如果 “细胞从存活的状态转变成死亡的状态”,我们将 board 中该位置的转态置为 -1;如果 “细胞从死亡的状态转变成存活的状态”,我们将 board 中该位置的状态置为 2。这里的 -12 可以是任意的数字,只要不和 01 重复即可。

需要注意的是,判断当前网格细胞是否是存活状态还要考虑 board[row][col] = -1 的情况。

最后,遍历 board,根据表示 “细胞从存活的状态转变成死亡的状态” 的 -1,将 board 中该位置置为 0,根据表示 “细胞从死亡的状态转变成存活的状态” 的 2,将 board 中该位置置为 1

实现代码

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        int dirs[] = {0, -1, 1};
        int rows = board.size();
        int cols = board[0].size();

        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols; ++col) {
                int cnts = 0;   // 表示周围相邻的八个方向上活细胞的数量
                for (int i = 0; i < 3; ++i) {
                    for (int j = 0; j < 3; ++j) {
                        if (!(dirs[i] == 0 && dirs[j] == 0)) {
                            int nRow = row + dirs[i];
                            int nCol = col + dirs[j];

                            // 更新 cnts
                            if (nRow >= 0 && nRow < rows && nCol >= 0 && nCol < cols && (abs(board[nRow][nCol]) == 1)) cnts += 1;
                        }
                    }
                }
                // 规则(1)(3)
                if (board[row][col] == 1 && (cnts < 2 || cnts > 3)) 
                    board[row][col] = -1;
                // 规则(4)
                if (board[row][col] == 0 && cnts == 3)
                    board[row][col] = 2;
            }
        }
        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols; ++col) {
                if (board[row][col] == -1) board[row][col] = 0;
                if (board[row][col] == 2) board[row][col] = 1;
            }
        }
    }
};

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为数组 board 的行数, n n n 为数组 board 的列数。

空间复杂度: O ( 1 ) O(1) O(1)


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。文章来源地址https://www.toymoban.com/news/detail-727542.html

到了这里,关于【面试经典150 | 矩阵】生命游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 1.5 面试经典150题 - 轮转数组

    轮转数组 给定一个整数数组  nums ,将数组中的元素向右轮转  k   个位置,其中  k   是非负数。 注意:本题需要原地操作 本题解题思路是: 以[]1, 2, 3, 4, 5, 6, 7] 3 为例 1. 先整体轮转,将 [1, 2, 3, 4, 5, 6, 7]转为 [7, 6, 5, 4, 3, 2, 1] 2. 再局部分别轮转前k个和剩余的,[5, 6, 7,   

    2024年01月16日
    浏览(37)
  • 面试经典150题——矩阵置零

    2.1 思路一——暴力求解 思路一很简单,就是尝试遍历矩阵的所有元素,如果发现值等于0,就把当前行与当前列的值分别置为0。同时我们需要注意,因为如果出现下图所示的情况: 比如发现 matrix[0][0] 等于0,我们把第一列和第一行置为0,但是被置为0的行的最后一个元素如上

    2024年02月21日
    浏览(40)
  • 1.6 面试经典150题 - 跳跃游戏

    跳跃游戏 给你一个非负整数数组  nums  ,你最初位于数组的  第一个下标  。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回  true  ;否则,返回  false  。 本题解题思路: 记录两个值:当前位置left,和目前可

    2024年01月19日
    浏览(86)
  • 面试经典150题:数组/字符串合集

    新专栏,预计两个月写完吧,每天下班回来抽空做几道题。会把做题计划顺序记录下来,如果你有缘,刷到这个开篇序列,那就跟着文章去练题吧。初学者可以慢慢来 88. 合并两个有序数组 27. 移除元素 这是前后指针覆盖做的,也可以双向指针交换做,思路 i从0开始,j从尾

    2024年02月08日
    浏览(42)
  • 【面试经典 150 | 数组】最后一个单词的长度

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年04月22日
    浏览(59)
  • 【面试经典150 | 矩阵】有效的数独

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年02月05日
    浏览(40)
  • 1.1 面试经典 150 题-合并两个有序数组

    合并两个有序数组

    2024年01月16日
    浏览(50)
  • 面试经典150题——删除有序数组中的重复项

    题目来源 力扣每日一题;题序:26 我的题解 方法一 双指针 使用两个指针分别指向相同元素的左右边界,再利用一个count记录最终需要的数组长度。 时间复杂度 :O(n) 空间复杂度 :O(1) 有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持

    2024年04月14日
    浏览(59)
  • LeetCode150道面试经典题-合并两个有序数组(简单)

    题目: 给你两个按 非递减顺序 排列的整数数组  nums1 和 nums2 ,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意: 最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对

    2024年02月14日
    浏览(44)
  • leetcode每日一题——189.轮转数组(面试经典150题)

    189. 轮转数组 - 力扣(LeetCode) 给定一个整数数组  nums ,将数组中的元素 向右轮转  k   个位置 ,其中  k   是非负数。 示例1: 示例2: 1 = nums.length = 105 -231 = nums[i] = 231 - 1 0 = k = 105        对题目进行分析可知,我们需要根据轮转量k,将数组后面的k个元素按照原来的顺

    2024年02月12日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包