手撕空间复杂度计算

2024年8月12日 | 分类: 【编程】

参考:https://blog.csdn.net/vpurple_/article/details/126018218

目录

0.前言

1.空间复杂度

1.1 大O的渐进表示法

1.2举几个计算空间复杂度的例子

1.2.1 计算冒泡排序的空间复杂度

1.2.1计算阶乘递归的时间复杂度

 1.2.3计算用数组实现还有用变量实现的斐波拉契数列的空间复杂度

 1.2.4计算用递归实现的斐波拉契数的空间复杂度

2.常见复杂度的对比



0.前言

相比而言现在算法不那么关注空间复杂度,因为现在的设备的存储空间都比较大。

1GB=1024*1024*1024字节   

1GB 大概是10亿字节

1MB 大概是100万字节

1GB=1024MB   1MB=1024KB   1KB=1024字节


1.空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 ,也就是额外占取的空间的大小。

空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。

空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。

注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。


1.1 大O的渐进表示法

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

O()括号里面的数更多的表达的是这个算法的量级,大O是一个估算,并不是准确的执行次数。

推导大O阶方法:

1、用常数1取代运行时间中的所有加法常数。

2、在修改后的运行次数函数中,只保留最高阶项。

3、如果最高阶项系数存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。


1.2举几个计算空间复杂度的例子

1.2.1 计算冒泡排序的空间复杂度

// 计算BubbleSort的空间复杂度?
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;
    }
}

冒泡排序的空间复杂度为:O(1)

分析如下:

1.2.1计算阶乘递归的时间复杂度

// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{
 if(N == 0)
 return 1;
 
 return Fac(N-1)*N;
}

 阶乘递归的时间复杂度:O(N).

分析如下:

 1.2.3计算用数组实现还有用变量实现的斐波拉契数列的空间复杂度

// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前n项
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;
}

用数组实现斐波拉契数列的空间复杂度:O(N).

用三个变量来回计算斐波拉契数列的空间复杂度是:O(N).

 1.2.4计算用递归实现的斐波拉契数的空间复杂度

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
 if(N < 3)
 return 1;
 
 return Fib(N-1) + Fib(N-2);
}

用递归实现的斐波拉契数的空间复杂度:O(N).

先计算一下在主函数中重复调用两个函数,函数所占用的空间大小。

空间是可以重复利用的。

把空间还给操作系统,释放了,而不是销毁了,只是把使用权交给操作系统了

空间复杂度基本上是O(1)或者O(N),其它的空间复杂度不常见。假设开一个N*N的数组,那么它的空间复杂度是O(N^2)。结构体不讨论结构体个数,只看整体。不看具体,只看量级。


2.常见复杂度的对比

一般算法常见的复杂度如下:

表格越往下复杂度相对越高

5201314

O(1)

常数阶
3log(2)n+4 O(log(2)n) 对数阶
3n+4 O(n) 线性阶
2n+3nlog(2)n+14 O(nlog(2)n) nlogn阶
3n^2+4n+5 O(n^2) 平方阶
4n^3+3n^2+4n+5 O(n^3) 立方阶
2^n O(2^n) 指数阶

图例如下所示:

 

请注意:\({log}_2{N}\) 与 \({log}{N}\) 是等价的。