【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

这样就能保证:

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

从而实现 原地更新矩阵


相关推荐
星轨初途2 小时前
郑州轻工业大学“筑梯杯” 2025级新生程序设计大赛暨省内高校邀请赛——题解
android·c++·经验分享·笔记·算法
淮南颂恩少儿编程2 小时前
淮南少儿编程 | CSP-J真题详解:在淮南也有接地气的算法课
c++·人工智能·python·深度学习·算法·青少年编程·蓝桥杯
zh路西法2 小时前
【宇树机器人强化学习】(五):go2奖励函数的实现与模型检验
python·深度学习·算法·机器学习·机器人
m0_748873552 小时前
模板编译期排序算法
开发语言·c++·算法
2401_842623652 小时前
基于C++的爬虫框架
开发语言·c++·算法
程序猿编码2 小时前
轻量又灵活:一款伪造TCP数据包的iptables扩展实现解析(C/C++代码实现)
linux·c语言·网络·c++·tcp/ip·内核·内核模块
j_xxx404_2 小时前
LeetCode模拟算法精解I:替换问号,提莫攻击与Z字形变换
开发语言·数据结构·c++·算法·leetcode
龙智DevSecOps解决方案2 小时前
邀请函 | 诚邀您参加Perforce on Tour 2026 游戏研发效能进阶沙龙(广州站),探索AI时代如何更高效、安全地开发游戏
游戏·ai·游戏开发·perforce·龙智
superkcl20222 小时前
C++初始化 和 赋值
开发语言·c++·算法