数据结构第三课补充(空间复杂度)

数据结构 算法空间复杂度分析

空间复杂度,衡量内存开销与问题规模 n 之间的关系,和时间复杂度共同构成算法效率的度量。

定义

空间复杂度:用于量度一个算法运行过程中临时占用的存储空间大小。

重要考点:只算辅助变量,不算输入数据本身所占的空间!

一般也作为问题规模n的函数,采用数量级形式描述,记作:
S(n)=O(g(n))

  • 若一个算法的空间复杂度为 O(1),则称此算法为原地工作 / 就地工作算法
    注意:O(1)不是完全不用空间,而是辅助空间大小和 n 无关,是固定常量。不是零空间!

一、普通非递归程序的分析方法

步骤:

  1. 找出辅助变量、动态数组中,大小会随 n 变化的变量。输入参数不算!
  2. 分析该空间 x 和 n 的关系:x=f(n)
  3. 取数量级,得到 S(n)=O(f(n))。
    小口诀:静态变量不算数,输入数组不算数,只看临时新开的。

示例1:O(1) 原地算法

c 复制代码
void loveYou(int n)
{
    int i=1;
    while(i<=n)
    {
        i++;
        printf("I Love You %d\n", i);
    }
    printf("I Love You More Than %d\n", n);
}
 

分析:变量 i 是固定单个变量,数量不随 n 变化。
👉 空间复杂度:S(n)=O(1)。

c 复制代码
int fun(int n)
{
    int i, j, k, s;
    s=0;
    for (i=0;i<=n;i++)
        for(j=0;j<=i;j++)
            for (k=0;k<=j;k++)
                s++;
    return(s);
}

分析:所有变量都是固定数量,循环只是执行次数变化,没有动态开辟数组。
👉 空间复杂度:S(n)=O(1)。

示例2:O(n),一维动态数组

c 复制代码
void test(int n)
{
    int flag[n];  // 长度为n的数组
    int i;
    // ...省略代码
}
 

分析:数组 flag 的大小等于 n,辅助空间随 n 线性增长。
👉 空间复杂度:S(n)=O(n)。

示例3:O(n²),二维动态数组

c 复制代码
void test(int n)
{
    int flag[n][n]; // n×n二维数组
    int i;
    // ...省略代码
}
 

👉 空间复杂度:S(n)=O(n²)。

多个数组叠加时,使用加法规则:O(f(n))+O(g(n))=O(max(f(n),g(n)))
例:同时有 flagnn 和 othern,S(n)=O(n2)+O(n)=O(n2),只保留最高阶。

一般关于数组:一旦形参涉及到数组

eg:imn O(n)=n 一维数组

imnn O(n)=n^2 二维数组

二、递归程序的分析方法

递归的空间复杂度 = 递归调用的最大深度!

每一层递归,栈上都会保存一层局部变量与参数。栈帧深度决定空间。

示例1:深度为 n 的递归

c 复制代码
void loveYou(int n)
{
    int a,b,c;
    if (n > 1) {
        loveYou(n-1);
    }
    printf("I Love You %d\n", n);
}

分析:调用链 loveYou(5) → loveYou(4) → ... → loveYou(1),递归深度 = n。
👉 空间复杂度:S(n)=O(n)。

示例2:每层递归再开一个数组

c 复制代码
void loveYou(int n)
{
    int flag[n];
    if (n > 1) {
        loveYou(n-1);
    }
    printf("I Love You %d\n", n);
}

分析:第n层开n个、n‑1层开n‑1个......总和 1+2+...+n≈\frac12 n^2。
👉 空间复杂度:S(n)=O(n²)。

⚠️ 坑点:不是只看单层,要累加整个递归栈的空间!

三、复杂度运算规则

  • 加法规则:O(f(n)) + O(g(n)) = O(max(f(n),g(n)))
  • 乘法规则:O(f(n)) × O(g(n)) = O(f(n)×g(n))

完整大小顺序(时间、空间通用):
O(1) < O(log₂n) < O(n) < O(nlog₂n) < O(n²) < O(n³) < O(2ⁿ) < O(n!) < O(nⁿ)

四、经典例题

例题1

算法的空间复杂度是指()。

A.算法中输入数据所占用的存储空间的大小

B.算法本身所占用的存储空间的大小

C.算法中所占用的所有存储空间的大小

D.算法中需要的辅助变量所占用存储空间的大小

答案:D

解析:输入数据的空间不计入空间复杂度。

例题2

某算法的空间复杂度为O(1),则()。

A.该算法执行不需要任何辅助空间

B.该算法执行所需辅助空间大小与问题规模n无关

C.该算法执行不需要任何空间

D.该算法执行所需空间大小与问题规模n无关

答案:B

解析:只针对辅助空间,不是全部空间。

例题3【判断题】

一个算法的空间复杂度是O(1),那么执行该算法时不需要任何空间。

答案:错

O(1)代表辅助空间是常量,仍然会用到少量变量空间,不是零。

五、空间复杂度做题通用步骤

  1. 区分输入与辅助:输入数组不算!只看算法自己临时开辟的变量、数组。
  2. 非递归:看动态数组的维度,一维O(n),二维O(n²),没有动态数组大多O(1)。
  3. 递归:找递归深度! 深度是多少,阶就是多少;每层还开数组,需要累加计算。
  4. 最后:忽略常数、系数、低阶项,保留最高阶得到大O。

背诵总结

  1. 空间复杂度只统计辅助存储空间,输入数据所占空间不计入。

  2. O(1)=原地算法:辅助空间是固定常量,不是完全不用空间。

  3. 普通程序:看动态数组;递归程序:空间复杂度主要由递归深度决定。

  4. 复杂度排序:O(1) < O(log₂n) < O(n) < O(nlog₂n) < O(n²) < O(n³) < O(2ⁿ)。

相关推荐
多弗朗皮卡丘1 小时前
数据结构6:队列
c语言·数据结构
PC2005-cloud1 小时前
Rust学习笔记:所有权、借用与生命周期——Rust的核心机制
笔记·学习·rust
xxxiugou1231 小时前
双指针解题秘籍:从入门到精通
c语言·数据结构·c++·算法
Logic1012 小时前
C语言/数据结构位运算题解:异或XOR找出地铁规划中的“独特坐标“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
沉淀的.晴天2 小时前
FreeRTOS信号量
数据结构·算法
霍金的微笑2 小时前
fuccc
学习
青山木3 小时前
Hot 100 --- 打家劫舍
java·数据结构·算法·leetcode·动态规划
潜心一志3 小时前
HALCON软件——数据结构
学习·计算机视觉
秦哈哈3 小时前
【HelloAgents】学习笔记(一)
学习·ai·agent