前言
前面向大家介绍了时间复杂度,其对提高算法效率起着至关重要的作用,现在存储设备发达,人们更注重于时间复杂度,某些特殊情况才会关注空间复杂度。对比时间复杂度,我们可以发现,时间是可以累积的,空间是可以重复利用的。理解这句话后能更好的计算时间复杂度和空间复杂度。
空间复杂度
空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度
。 空间复杂度不是程序占用了多少bytes
的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂度类似,也使用大
O
渐进表示法
。
注意:函数运行时所需要的栈空间
(
存储参数、局部变量、一些寄存器信息等
)
在编译期间已经确定好了,因
此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
空间复杂度例题
例1:
void F1(int n)
{
int a = 0;
int* p = (int*)malloc(4 * n);
printf("%p %p\n", &a, &p);
if (p == NULL)
{
perror("malloc fail");
return;
}
free(p);
}
int main()
{
F1(10);
F1(10);
return 0;
}
通过对两次函数调用并打印其调用时用到的空间可以发现,其两次调用用的是同一个空间。
例2:冒泡排序
// 计算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)。
例3:
long long Fib(size_t N)
{
if (N < 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}
在计算过程中,不断地调用Fib()函数,只是传参不同,但是使用的是同一个函数栈帧,并没有开辟新空间,故空间复杂度为O(1)。
例4:
在介绍时间复杂度时,附加题数组倒置中方法二
void rotate(int* nums, int numsSize, int k)
{
int i = 0;
int j = 0;
if (k > numsSize)
k = k % numsSize;
if (k == numsSize)
{
for (i = 0; i < numsSize; ++i)
{
printf("%d", nums[i]);
}
}
else
{
int left = numsSize - k;
int right = k;
int* arr1 = (int*)malloc(sizeof(int) * left);
int* arr2 = (int*)malloc(sizeof(int) * right);
if(arr1==NULL || arr2==NULL)
{
printf("malloc fail");
return;
}
for (i = 0; i < numsSize; ++i)
{
if (i < left)
arr1[i] = nums[i];
else
{
arr2[j] = nums[i];
j++;
}
}
for (i = 0, j = 0; i < numsSize; ++i)
{
if (i < right)
nums[i] = arr2[i];
else
{
nums[i] = arr1[j];
j++;
}
}
free(arr1);
free(arr2);
}
}
其过程中,我们临时开辟了两个空间,用于暂时存放数组内容,在创建空间中,我们创建的空间存放数据的个数为N,所以该方法的空间复杂度为O(N)。