如何评价一段代码或算法的性能和好坏?目前衡量代码质量的指标主要有两个:分别为时间复杂度和空间复杂度。其中时间复杂度指的是执行当前算法所消耗的时间,空间复杂度指的是指执行当前算法需要占用多少内存空间。有的时候时间和空间是不可兼得的,需要从中去取一个平衡点。下面简单描述一下如何计算时间复杂度和空间复杂度
一、时间复杂度
利用大O符号表示法来表示时间复杂度,即T(n) = O(f(n))。其中f(n) 表示每行代码执行次数之和,而 O 表示正比例关系,这个公式的全称是:算法的渐进时间复杂度。
for(i=1; i<=n; ++i)
{
j = i;
j++;
}
(1+n+n)*time :T(n) = O(n) 。因为大O符号表示法并不是用于来真实代表算法的执行时间的,它是用来表示代码执行时间的增长变化趋势的。假设n为无穷大时,倍数2和加数1可以忽略不计。
目前常见的时间复杂度量级有以下几种,按照顺序时间复杂度越来越大,执行的效率越来越低:
(1)常数阶O(1); (2)对数阶O(logN); (3)线性阶O(n); (4)线性对数阶O(nlogN);
(5)平方阶O(n²); (6)立方阶O(n³); (7)K次方阶O(n^k); (8)指数阶(2^n)。
下面主要介绍几种常见的时间复杂度计算案例:
1、常数阶O(1)
k=i;
i=j;
j=k;
j++;
2、对数阶O(logN)
int i = 1;
while(i<n)
{
i = i * 2;
}
上面的代码可以发现循环并不是到n结束,因为i的值在变化,i每次都在乘以2,2^x=n为终止条件,此时x也就为logN。
3、线性阶O(n)
for(i=1; i<=n; i++)
{
j = i;
j++;
}
4、线性对数阶O(nlogN)
for(m=1; m<n; m++)
{
i = 1;
while(i<n)
{
i = i * 2;
}
}
5、平方阶O(n²)
for(x=1; i<=n; x++)
{
for(i=1; i<=n; i++)
{
j = i;
j++;
}
}
时间复杂度为 O(n²)。
for(x=1; i<=m; x++)
{
for(i=1; i<=n; i++)
{
j = i;
j++;
}
}
时间复杂度为 O(m*n)。
二、空间复杂度
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。空间复杂度比较常用的有:O(1)、O(n)、O(n²)。
1、空间复杂度 O(1)
如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)。
int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
代码中的 i、j、m 所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1)。
2、空间复杂度 O(n)
int[] m = new int[n]
for(i=1; i<=n; ++i)
{
j = i;
j++;
}
这段代码中,第一行new了一个数组出来,这个数据占用的大小为n,这段代码的2-6行,虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n)。
3、空间复杂度O(N2)
int[][] arr = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = new Random().nextInt();
}
}
随着数据量的变化,内存消耗为平方变化。