【LeetCode 289】生命游戏(C语言)|原地算法 + 状态标记法

一、题目描述

根据百度百科,生命游戏(Game of Life)是英国数学家 约翰·何顿·康威 在 1970 年提出的细胞自动机模型。

给定一个 m × n 的网格 board,每个位置表示一个细胞:

  • 1 表示 活细胞

  • 0 表示 死细胞

每个细胞与其 八个相邻位置(上下左右 + 四个对角线)共同决定下一状态。

细胞演化规则

1️⃣ 活细胞周围 少于 2 个活细胞 → 死亡(模拟人口不足)

2️⃣ 活细胞周围 2 或 3 个活细胞 → 继续存活

3️⃣ 活细胞周围 超过 3 个活细胞 → 死亡(模拟人口过多)

4️⃣ 死细胞周围 恰好 3 个活细胞 → 复活

要求:

所有细胞必须同时更新


二、解题思路

如果直接修改 board[i][j],会影响后续邻居统计。

例如:

复制代码
先更新 (0,0)
再计算 (0,1)

此时 (0,1) 读取到的是 更新后的状态,结果就错了。

解决办法:状态标记法(原地算法)

利用额外状态记录:

原状态 新状态 编码
0 0 0
1 1 1
1 0 -1
0 1 2

解释:

  • -1:原来是 活细胞 → 死亡

  • 2:原来是 死细胞 → 复活

判断邻居是否原本是活细胞:

复制代码
abs(board[x][y]) == 1

因为:

复制代码
1  -> 原本活
-1 -> 原本活

三、算法流程

第一步:统计邻居

遍历每个细胞 (i,j),统计 8 个方向活细胞数量。

方向数组:

复制代码
(-1,-1) (-1,0) (-1,1)
(0,-1)        (0,1)
(1,-1)  (1,0) (1,1)

第二步:更新状态

如果当前是活细胞:

复制代码
live < 2 或 live > 3
→ 标记为 -1

如果当前是死细胞:

复制代码
live == 3
→ 标记为 2

第三步:恢复最终状态

最后再遍历一遍:

复制代码
>0  → 1
<=0 → 0

四、C语言实现

复制代码
#include <stdlib.h>

void gameOfLife(int** board, int boardSize, int* boardColSize) {

    int m = boardSize;
    int n = boardColSize[0];

    int dirs[8][2] = {
        {-1,-1},{-1,0},{-1,1},
        {0,-1},        {0,1},
        {1,-1},{1,0},{1,1}
    };

    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
        {
            int live = 0;

            for(int k = 0; k < 8; k++)
            {
                int x = i + dirs[k][0];
                int y = j + dirs[k][1];

                if(x >= 0 && x < m && y >= 0 && y < n && abs(board[x][y]) == 1)
                    live++;
            }

            if(board[i][j] == 1)
            {
                if(live < 2 || live > 3)
                    board[i][j] = -1;
            }
            else
            {
                if(live == 3)
                    board[i][j] = 2;
            }
        }
    }

    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(board[i][j] > 0)
                board[i][j] = 1;
            else
                board[i][j] = 0;
        }
    }
}

五、复杂度分析

时间复杂度

复制代码
O(m × n)

每个细胞最多检查 8 个邻居。


空间复杂度

复制代码
O(1)

使用 状态标记法实现原地更新,没有额外数组。


六、总结

本题核心思想:

使用额外状态记录"过去状态"

关键技巧:

复制代码
1 -> 0   用 -1
0 -> 1   用 2

判断原状态:

复制代码
abs(board[i][j]) == 1

这样就能保证:

在更新过程中仍然可以获取到 原始状态

从而实现 原地更新矩阵。


相关推荐
Navigator_Z15 分钟前
LeetCode //C - 1269. Number of Ways to Stay in the Same Place After Some Steps
c语言·算法·leetcode
2601_9657422218 分钟前
短视频脚本创作方法分享:本地生活类账号的起步思路
大数据·人工智能·算法·ai·新媒体运营·生活
55873生态系统手记26 分钟前
读完 55873 资产钱包的技术栈,我重新理解了 "合规钱包" 应该长什么样
算法·架构
旋生万物29 分钟前
素数螺旋映射 $z_n=n^{1+i}$ 的角分布统计检验与零模型对比
大数据·前端·人工智能·算法·云原生·螺旋生成论·螺旋相位
HRTOS31 分钟前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机
邵奈一1 小时前
当沉香之乡遇上 Seed-2.1-pro:我用 AI 给村子做了一个数字门面
算法·架构
垆边人似月.1 小时前
华为机考题:矩阵中的最长递增路径
c语言·c++
海天一色y1 小时前
图像分割全解析:从经典算法到深度学习的原理与实战(Python + MATLAB)
python·深度学习·算法
SelectDB技术团队1 小时前
ClickHouse 存日志的能力边界:并发、检索与 trace 回放的实测对照
数据结构·数据库·clickhouse·日志分析·apache doris·日志存储
垆边人似月.1 小时前
华为算法题:最长连续递增子序列的变
数据结构·算法·leetcode