【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

这样就能保证:

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

从而实现 原地更新矩阵


相关推荐
AI科技星2 分钟前
《全域数学》第一部 数术本源 第三卷 代数原本第14篇 附录二 猜想证明【乖乖数学】
人工智能·算法·数学建模·数据挖掘·量子计算
Wect16 分钟前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
yzq19912720 分钟前
C语言#和##的用法(附带示例)
c语言·宏定义·预处理运算符·字符串化·标记连接
憨波个24 分钟前
【说话人日志】DOVER-Lap:overlap-aware diarization 输出融合算法
人工智能·深度学习·算法·音频·语音识别
叼烟扛炮31 分钟前
C++第四讲:类和对象(下)
c++·算法·类和对象
Rabitebla31 分钟前
vector 的骨架:三根指针、模板陷阱与迭代器失效的第一现场
开发语言·数据结构·c++·算法
念威43 分钟前
弹幕互动游戏AI无人直播方案 - 可遇AI无人直播助手
人工智能·游戏
代码不停1 小时前
BFS解决floodfill算法题目练习
算法·宽度优先
风酥糖1 小时前
Godot游戏练习01-第33节-新增会爆炸的敌人
游戏·游戏引擎·godot
上弦月-编程1 小时前
C语言指针从入门到实战
java·jvm·算法