跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客工具镜像开源精选AI社区
我的书AI 学习话题UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++AI算法

空间复杂度怎么判断:几个常见例子讲透

空间复杂度关注的是算法运行时额外占用的存储,而不是程序总内存。文章通过动态二维数组、冒泡排序、斐波那契数组和递归阶乘几个例子说明:显式申请的堆空间会随输入规模增长,原地排序通常是 O(1),递归则要把调用栈深度算进去,很多时候空间开销就藏在这里。

2177283801发布于 2026/6/30更新于 2026/11/1382 浏览
空间复杂度怎么判断:几个常见例子讲透

算法的空间复杂度

算法运行时,除了时间,还会占用一部分空间。做算法分析时,时间复杂度大家看得多,空间复杂度往往容易被顺手带过,但在内存吃紧、递归层数深,或者要做大规模数据处理时,它一点也不轻。

空间复杂度主要看的是算法额外占用的存储空间,不是程序最终一共用了多少内存。后者受运行环境、编译器、库函数影响太大,拿来比较没什么意义。我们真正关心的是:输入规模变大时,额外空间怎么涨。

核心定义

算法空间复杂度通常写成一个数学表达式,用来描述算法在运行过程中额外临时占用的存储空间规模。

  • 关注的是额外空间,不是输入本身占了多少。
  • 计算时通常按变量个数、递归栈深度、动态申请的空间来估算。
  • 表达方式和时间复杂度一样,一般也用大 O 表示法。

函数运行时的栈空间也算在内。参数、局部变量、返回地址这些内容,通常会随着递归深度或调用层数变化,不能直接忽略。

常见空间复杂度计算示例

下面几个例子,基本能覆盖日常最常见的几种情况。

1. 动态二维数组分配

int** fun(int n) {
    int** s = (int**)malloc(n * sizeof(int*));
    for (size_t i = 0; i < n; ++i) {
        s[i] = (int*)malloc((i + 1) * sizeof(int));
    }
    return s;
}

这里申请的是一个'行数递增'的二维数组。第 1 行 1 个元素,第 2 行 2 个元素,一直到第 n 行。

总元素个数是 1 + 2 + ... + n,结果是 n(n + 1) / 2。去掉常数和低阶项以后,空间复杂度就是 O(n²)。

2. 冒泡排序

void BubbleSort(int* a, int n) {
    assert(a);
    for (size_t end = n; end > 0; --end) {
        int exchange = ;
         ( i = ; i < end; ++i) {
             (a[i - ] > a[i]) {
                (&a[i - ], &a[i]);
                exchange = ;
            }
        }
         (exchange == ) ;
    }
}
0
for
size_t
1
if
1
Swap
1
1
if
0
break

这个实现是原地排序,额外只用了 end、exchange、i 这几个变量。它们的数量不会随着 n 变大而增加,所以空间复杂度是 O(1)。

3. 斐波那契数列

long long* Fibonacci(size_t n) {
    if (n == 0) return NULL;
    long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));
    fibArray[0] = 0;
    fibArray[1] = 1;
    for (int i = 2; i <= n; ++i) {
        fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
    }
    return fibArray;
}

这里直接申请了 n + 1 个 long long 空间来保存结果。输入规模越大,数组越长,空间也按线性增长,所以复杂度是 O(N)。

4. 递归阶乘

long long Fac(size_t N) {
    if (N == 0) return 1;
    return Fac(N - 1) * N;
}

递归函数看起来代码很短,空间账却不便宜。它会一路调用到 N == 0,调用栈上会压下 N 层栈帧。每层栈帧消耗的空间是常数级,所以总空间复杂度是 O(N)。

递归的空间复杂度,通常看的是'递归深度 × 单层栈帧开销'。这个判断比只看代码长度靠谱得多。

实际分析时怎么想

我一般先分两类看:一类是显式申请的堆空间,比如 malloc、new;另一类是函数调用带来的栈空间,尤其是递归。前者比较直观,后者经常被漏掉,但线上出问题时往往就是它先顶不住。

同样的功能,写法不同,空间占用可能差很多。能原地做的就别多开数组;递归写起来顺手,但如果递归层数会很深,最好提前想清楚栈会不会扛不住。这个取舍没有标准答案,要看数据规模和运行环境。

小结

空间复杂度主要看额外空间,而不是程序最终占了多少内存。分析时重点关注动态申请的存储、递归带来的栈帧,以及那些会随输入规模增长的数据结构。像冒泡排序这种原地算法,额外空间是常数;像动态二维数组、递归阶乘这类实现,空间会随着 n 明显增长。实际写代码时,时间和空间很少能同时占优,通常得按场景选一个更合适的平衡点。

目录

  1. 算法的空间复杂度
  2. 核心定义
  3. 常见空间复杂度计算示例
  4. 1. 动态二维数组分配
  5. 2. 冒泡排序
  6. 3. 斐波那契数列
  7. 4. 递归阶乘
  8. 实际分析时怎么想
  9. 小结

更多推荐文章

查看全部
  • FastDFS-Client 分布式文件存储系统使用指南
  • C++ 面试题常用总结详解
  • HTML 核心语法与结构实战指南
  • 基于动态反演与 ESO 的无人机鲁棒反馈线性化自适应姿态控制
  • Spring MVC Web 开发实战:接口约定与前后端交互
  • 多模态大模型综述:从基础模型到智能代理
  • AI绘画建筑设计提示词:从基础到高级的完整创作指南
  • 飞书 CLI 开源指南:AI 接管办公全流程实战
  • OpenClaw 的 20 个精选 Skills 使用指南与实战技巧
  • 如何利用大模型提升学习效率:方法与实践
  • 普通程序员学习大模型(LLM)路线与知识体系指南
  • Llama3 中文通用 Agent 微调模型实战教程
  • 构建 AI 临床副驾驶:基于 Go 的电子病历助手与 HIS 对接实战
  • Wan2.1-I2V 基于步数蒸馏实现 RTX 4060 快速视频生成
  • C++ string 类基础用法与经典算法题解析
  • 使用 Docker 在 Ubuntu 虚拟机中安装 OpenClaw
  • C++ 多态详解:虚函数、重写与底层原理
  • 程序员接单兼职平台盘点与选择指南
  • 大语言模型 LLM 解决 AI 幻觉方法深度分析
  • Linux 进程控制:自主 Shell 命令行解释器实现

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online