时间复杂度和空间复杂度是衡量算法效率的重要指标,二者也都主要是分析问题规模T(n)的数量级的函数,那么它们具体是怎么样计算的呢?
时间复杂度
一个语句的频度是指该语句在算法中被重复执行的次数,算法中所有语句的频度之和记为T(n),它是和问题规模n的函数,时间复杂度主要是分析T(n)的数量级。
所以什么是算法的时间复杂度?
简单来说就是对算法的时间开销与问题规模n关系的事先预估。
那要如何去计算呢?
⑴ 找出算法中的基本运算;通常我们不用去计算所有的语句频度,即T(n),直接基本运算语句的频度即可。(除非需要完整的分析过程)
算法中执行次数最多的那条语句就是基本语句,通常是最深层循环中的语句。
⑵ 计算基本语句的执行次数的数量级;
只需保留f(n)中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。
⑶ 用大Ο记号表示算法的时间性能。
将基本语句执行次数的数量级放入大Ο记号中。
如果算法中包含嵌套的循环,则基本语句通常是最内层的循环体,如果算法中包含并列的循环,则将并列循环的时间复杂度相加。
例如:
int sum=0; /*执行一次*/
for(int i=0;i<n;i++) /*执行n+1次*/
{ sum+=i; /*执行n次*/
}
所以时间复杂度为O(1+n+n+1)=O(n)
例如:
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;i<n;j++)
{ sum+=1; /*直接找到最深层循环的语句就好,这里执行n*n次*/
}
所以时间复杂度为O(n^2)
例如:
int sum=1;
for(int i=1;i<n;)
{ i=i*2;
sum++ /*执行log2 n次*/
}
此时时间复杂度为O(log2 n)
不熟练的话我们可以罗列一下,假如n为16
那i的值为1 2 4 8 16 ,在16的时候就已经跳出循环了,所以sum++语句频度是4次。
例如:
sum=0;
for(int i=0;i*i*i<=n;i++)
{
sum++;/*执行n^(1/3)次*/
}
当i<=n^(1/3)的时候,sum++才执行。
所以时间复杂度为O(n^(1/3))
例如:
int func(int n)
{
int sum=0;
int a=1;
int b=2
sum=a+b;
}
时间复杂度为O(1)
其实这个代码的语句频度应该是4,那为什么不是O(4)呢?
时间复杂度是分析问题规模n的函数,但是这段代码的语句执行次数不受问题规模n的影响,n为1或者10000,函数内语句执行的次数都为一个常数,也就是一次就能执行完。(我的例子可能有些不恰当,但是意思还是一样的)
若运行时间跟n的取值无关,即无论n取什么值,运行时间都不会变,则时间复杂度为O(1),只要基本操作执行次数是个常量,时间复杂度都为O(1)。
例如:
for(m=1; m<n; m++) /*循环n次*/
{
i = 1;
while(i<n)
{
i = i * 2; /*一次循环执行log2 n次*/
}
}
时间复杂度为O(nlog2 N)
空间复杂度
影响算法空间复杂度的因素有存储算法本身需要的空间以及在运行过程中需要临时申请的空间,但是对算法存储空间影响最大还是临时申请的空间,所以空间复杂度主要是对一个算法在运行过程中临时占用存储空间大小的一个量度,用 S(n) 来定义。
例如:
int m[10];
for(i=1; i<10; i++)
{
m[i]=i;
}
此时空间复杂度为S(n)=O(1),此时算法的占用的空间与问题规模没有任何关系,无论问题规模多大,算法占用的空间是不变的,此时空间复杂度便为常数阶O(1)。
同时当一个算法的空间复杂度为O(1)时,便称算法可以原地工作,即不需要任何额外的辅助,算法所需要的辅助空间不随着问题的规模而变化,是一个确定的值。
例如:
int j=0;
int[] m = new int[n]
for(i=1; i<=n; ++i)
{
j = i;
j++;
}
此时算法的空间复杂度为O(n),算法所需要的临时空间和问题规模是成线性关系的,n越大,所需空间便越大。
时空复杂度(时间复杂度/空间复杂度)O(1)、O(n)、O(n^2)、O(log n)、O(n log n)详细解释
大小:O(1)<O(logN)<O(n(1/2))<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
部分图像表示:
1.O(n):就代表数据量增大几倍,耗时也增大几倍。比如常见的遍历算法。
2.O(n*n),就代表数据量增大n倍时,耗时增大n的平方倍,这是比线性更高的时间复杂度。比如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。
3.O(logn),当数据增大n倍时,耗时增大logn倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。二分查找就是O(logn)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。
3.O(nlogn)同理,就是n乘以logn,当数据增大256倍时,耗时增大256*8=2048倍。这个复杂度高于线性低于平方。归并排序就是O(nlogn)的时间复杂度。
4.O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话)