【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

这样就能保证:

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

从而实现 原地更新矩阵


相关推荐
hhh3u3u3u3 小时前
Visual C++ 6.0中文版安装包下载教程及win11安装教程
java·c语言·开发语言·c++·python·c#·vc-1
AI应用实战 | RE3 小时前
012、检索器(Retrievers)核心:从向量库中智能查找信息
人工智能·算法·机器学习·langchain
凤年徐3 小时前
C++手撕红黑树:从0到200行,拿下STL map底层核心
c++·后端·算法
泛凡(Linyongui)3 小时前
PY32F002B实践之二--宠物腹背理疗仪项目介绍及头文件解析
c语言·keil·py32·32位单片机·腹背理疗仪项目实践
Thomas.Sir3 小时前
AI 医疗之罕见病/疑难病辅助诊断系统从算法到实现【表型驱动与知识图谱推理】
人工智能·算法·ai·知识图谱
tankeven4 小时前
动态规划专题(03):区间动态规划从原理到实践(未完待续)
c++·算法·动态规划
田梓燊5 小时前
2026/4/11 leetcode 3741
数据结构·算法·leetcode
斯内科5 小时前
FFT快速傅里叶变换
算法·fft
葳_人生_蕤5 小时前
hot100——栈和队列
数据结构
2301_822703205 小时前
开源鸿蒙跨平台Flutter开发:幼儿疫苗全生命周期追踪系统:基于 Flutter 的免疫接种档案与状态机设计
算法·flutter·华为·开源·harmonyos·鸿蒙