时间复杂度与空间复杂度

Posted 银背欧尼酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了时间复杂度与空间复杂度相关的知识,希望对你有一定的参考价值。


前言

数据结构与算法是程序员的必修课。从这篇文章开始,我们就正式进入了数据结构与算法的学习。本篇文章介绍了几个算据结构的基本概念,让我们一起看一下。


1.算法效率与时间复杂度

数据结构:数据结构是计算机存储,组织数据的方式,指相互之间存在一种或多种特定关系的数组元素的集合

算法:算法就是一系列的计算步骤,用来将输入数据转化成输出结果

算法效率

算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间,在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。我们更关注算法的时间复杂度,也常使用以空间换时间的策略。

时间复杂度:

一个算法的运行时间和语句的执行次数成正比,且同一个算法在不同机器上的运行时间都不同,不好量化。所以令算法中的基本操作的执行次数,为算法的时间复杂度。

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行的次数,这里我们用大O的渐进表示法。且大O渐进表示法计算的是算法最坏的情况。

简言之:大O表示法是忽视了系数,只看最高次项的一种方法。

例:

// 计算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;
	}
}
 
 最坏执行了(N*(N+1)/2次,时间复杂度为 O(N^2)
// 计算Func3的时间复杂度?
void Func3(int N, int M) {
	int count = 0;
	for (int k = 0; k < M; ++k) {
		++count;
	}
	for (int k = 0; k < N; ++k) {
		++count;
	}
	printf("%d\\n", count);
}
基本操作执行了M+N次,时间复杂度为 O(N+M)
// 计算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);
}
基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N)

2.空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度算的是变量的个数,计算规则和时间复杂度类似,也用大O渐进表示法

// 计算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)
// 计算Fibonacci的空间复杂度?
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(N)
// 计算阶乘递归Factorial的空间复杂度?
long long Factorial(size_t N) 
{
	return N < 2 ? N : Factorial(N - 1) * N;
} 
 递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)

总结

以上就是今天要讲的内容,本文仅仅简单介绍了时间复杂度和空间复杂度的概念,并举出了几个例子以供参考加深理解。

以上是关于时间复杂度与空间复杂度的主要内容,如果未能解决你的问题,请参考以下文章

关于代码片段的时间复杂度

以下代码片段的时间复杂度是多少?

重学数据结构与算法系列:时间复杂度与空间复杂度

时间复杂度与空间复杂度

时间复杂度与空间复杂度的理解与计算

以下代码片段的算法复杂度