为什么要分析时空复杂度?
算法的时空复杂度越低,其效率就越高。算法复杂度是衡量程序优劣及效率的重要指标。
对于ACMer来说,我们面对的问题是完成可以在时空限制要求内对给定输出返回正确输出的代码,所以我们必须要结合数据范围对算法进行时空复杂度分析。
时间复杂度(比较重要)
时间频度
一个算法执行所耗费的时间不仅仅与代码有关,必须上机运行测试才能知道。但我们可以对代码运行的时间进行粗略分析。
一个算法花费的时间与算法中语句的执行次数成正相关。一般来说,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度,记为T(n)。(n为输入数据的规模,例如输入含有n个元素的数组a[],让我们将a[]数组排序。)
时间复杂度
引入时间复杂度概念。在写完代码时候再逐条统计语句的运行次数太过麻烦而没有必要。
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。时间复杂度是问题规模趋于无穷时算法运行时间优劣的比较依据。
一般来说取T(n)最高次项,并舍掉其系数即可作为其时间复杂度。常见的时间复杂度有:O(1) < O(logn) < O(n) < O(nlogn) < O ( n 2 ) O(n^{2}) O(n2) < O ( n 3 ) O(n^3) O(n3) < O ( 2 n ) O(2^n) O(2n) < O(n!)等。
ACM中的时间复杂度
我们无需对每道题的时间复杂度严格证明,只需粗略分析代码是否会超时。
在竞赛中,一般认为计算机一秒能执行
5
∗
1
0
8
5*10^8
5∗108 次计算,如果题目给出的时间限制为1秒,那么选择的算法执行的计算次数最多应该在
1
0
8
10^8
108量级才有可能解决这个题目。
一般情况下:
以上范围仅供参考,实际过程中还要考虑每种算法的常数。
空间复杂度(不怎么重要)
空间复杂度
空间复杂度类似于时间复杂度的讨论,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
算法的输入输出数据所占用的存储空间是由要解决的问题决定的,所以
存储算法本身所占用的存储空间在完成代码之后为一个常量,并不重要,在竞赛中若存在代码长度限制一般会另行规定。
算法在运行过程中临时占用的存储空间随算法的不同而异,并不会超过时间复杂度。
可以发现空间复杂度一定不会超过时间复杂度。综上,所以没有什么人分析空间复杂度。
ACM中的空间限制
通过定义变量所占字节数的累加我们可以求得代码所使用的空间。但空间卡得很死的题一般被称作毒瘤题,所以以下内容但当涉猎。
了解空间的计算之前,我们先来了解一下计算机储存的单位B(Byte)。
1KB=1024B
1MB=1024KB
1Gb=1024MB
知道这些后,我们来了解各种类型所占的B(字节)数,就可以进行空间复杂度计算了。
数据类型\编译平台 | 16位 | 32位 | 64位 |
---|---|---|---|
char | 1 | 1 | 1 |
int | 2 | 4 | 4 |
long long | 4 | 4 | 8 |
float | 4 | 4 | 4 |
double | 8 | 8 | 8 |
short | 2 | 2 | 2 |
指针 | 2 | 4 | 8 |