目录
一、什么是空间复杂度
空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用额外存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因 此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
二、常见的空间复杂度计算举例
例1.
// 计算Func2的时间复杂度?
void Func2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}
和时间复杂度不同,空间是可以重复使用的,不用累计计算。
所以,BubbleSort的空间复杂度为F(N) = (3)
使用大O的渐进表示法后空间复杂度为 O(1)
例2.
// 计算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;
}
额外开辟了n个空间
使用大O的渐进表示法后空间复杂度为 O(N)
例3.
// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{
if(N == 0)
return 1;
return Fac(N-1)*N;
}
每次的递归调用都会开辟栈帧,每个栈帧使用了常数个空间
使用大O渐近表示法:O(N)
例4.
long long Fib(size_t N)
{
if(N < 3)
return 1;
return Fib(N-1) + Fib(N-2);
}
每次的递归调用都会开辟栈帧,栈帧销毁了可重复利用,所以递归算法的空间复杂度取决于每次调用的空间复杂度和最大递归深度
使用大O渐近表示法:O(N)
三、空间复杂度相关题目
1. 移除元素
移除元素
题述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,必须仅使用O(1) 额外空间并 原地 修改输入数组。
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
int removeElement(int* nums, int numsSize, int val)
{
int f = 0;
int s = 0;
for(f = 0; f < numsSize; f++)
{
if(nums[f] != val)
{
nums[s] = nums[f];
s++;
}
}
return s;
}