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

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

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

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

算法的空间复杂度

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

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

核心定义

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

  • 关注的是额外空间,不是输入本身占了多少。
  • 计算时通常按变量个数、递归栈深度、动态申请的空间来估算。
  • 表达方式和时间复杂度一样,一般也用大 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 = 0;
        for (size_t i = 1; i < end; ++i) {
            if (a[i - 1] > a[i]) {
                Swap(&a[i - 1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 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. 小结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 在 Qt Creator 里启用 GitHub Copilot
  • 2025 年 AI IDE 怎么选:Trae、Copilot、Windsurf、Cursor 实测对比
  • GLPI 安装与基础配置笔记
  • Vivado AXI4-Stream Data FIFO 配置与仿真记录
  • Web 开发里的 5 种加密算法:原理与代码
  • Spring 国际化原理与实战:MessageSource、LocaleResolver、LocaleContextHolder、MessageFormat
  • C++ list 容器的用法与简化实现
  • OpenClaw 飞书机器人部署记录
  • StyleSelectorXL:在 SDXL 里管理 77 种绘画风格
  • 修复 Copilot 和 Codex 写入中文乱码
  • OpenClaw 记忆系统实践:Token 压缩、分层记忆与定时反思
  • LLaMA-Factory 微调入门与实战配置
  • 大模型面试题整理:RAG、SFT、RLHF 与核心架构
  • 腾讯 Claw 三款 AI Agent 横评:WorkBuddy、QClaw、CodeBuddy 怎么选
  • 腾讯三款 AI Agent 怎么选:WorkBuddy、QClaw、CodeBuddy 实测
  • Python 缓存策略:从 dict 到 LRU 与分布式实战
  • 海尔智能家居接入 HomeAssistant 指南
  • VS Code Copilot Chat 扩展排障实录
  • Claude Code 安装与使用实录
  • 用 AI 把网页 URL 生成 Tailwind CSS 的实战记录

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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