赞
踩
数据结构是程序的骨架,算法是程序的灵魂。
算法是对特定问题求解步骤的一种描述。
基本标准
其他标准
高效性 :运行效率高,算法运行时间短。
衡量一个算法的高效性,通常我们从时间和空间两个维度去考量。
低存储性:算法所需的存储空间小。
时间复杂度
我们知道,对于一个算法的执行时间有:
算法执行的总时间 = 算法中的每条语句执行时间之和
通常情况下,我们可以假设算法的每条语句执行一次所需要的时间为单位时间1,那么算法的执行时间则与算法中需要执行语句的数量成正比,因此,我们可以通过算法中语句数量的总和作为算法时间复杂度的评判标准。
其对应的公式如下:
T
[
n
]
=
O
(
f
(
n
)
)
(1)
T[n]=O(f(n))\tag{1}
T[n]=O(f(n))(1)
其中
O
O
O代表的是代码执行时间随数据规模增长变化的趋势,即渐进时间复杂度(简称时间复杂度)。
下面我们结合例子具体分析:
int sum = 0; //运行1次
int total = 0; //运行1次
for(int i = 1; i <= n; i++) //运行n+1次(其中1代表最后一次判断不满足循环条件)
{
sum = sum + i; //运行n次
for(int j = 1; j <= n; j++) //运行n(n+1)次
{
total = total + i + j; //运行n*n次
}
}
该例子中,
T
(
n
)
=
O
(
2
n
2
+
3
n
+
3
)
T(n)=O(2n^2+3n+3)
T(n)=O(2n2+3n+3),当n足够大的时候,低阶、常数项和系数对
T
(
n
)
T(n)
T(n)的增长趋势起不到决定性的作用,即其并不能左右
T
(
n
)
T(n)
T(n)的增长趋势,因此可以忽略不计,我们可将其简化为
T
(
n
)
=
O
(
n
2
)
(2)
T(n)=O(n^2)\tag2
T(n)=O(n2)(2)
通常情况下,我们在求一个算法的时间复杂度的时候,我们都会将n看作一个很大的数(因为只有当n很大的时候探讨算法的效率才有意义)。因此我们只需要考虑分析它的高阶项即可。
对于部分语句不太好计算运行次数的算法,我们可以对其进行简单的假设,然后进行求解,例子如下:
int = 1; //运行1次
while(i <= n) //假设运行x+1次
{
i = i * 2; //运行了x次
}
对于while
循环中内容我们无法立即确定其运行了多少次,我们可以先假设其运行了x次,每次循环后i的值为
2
2
2、
2
2
2^2
22、
2
3
2^3
23、
2
4
2^4
24、… 、
2
x
2^x
2x,当i=n的时候循环结束,即
x
=
l
o
g
2
n
x=log_2{n}
x=log2n,因此上例,运行次数为
2
l
o
g
2
n
+
2
2log_2{n}+2
2log2n+2,因此其对应的复杂度为
T
(
n
)
=
O
(
l
o
g
2
n
)
T(n)=O(log_2{n})
T(n)=O(log2n)
但是并不是所有的算法都能够直接计算其运算次数的。例如:
int findx(int x) //在a[n]数组中顺序查找x
{
for(int i = 0; i < n; i++)
{
if(a[i] == x) //查找成功,返回其下标
{
return i;
}
}
return -1; //查找失败,返回-1
}
对于上例的算法,我们很难计算其到底执行多少次,因为运算次数强依赖于x在数组中的位置,且其位对于不同目标x,位置是不同的,如果第一个元素就是x,则其循环执行一次(最好的情况);如果是最后一个元素是x,则循环需要执行n次(最坏的情况)。如果x的位置概率均等,则循环平均运行次数为 ( n + 1 ) / 2 (n+1)/2 (n+1)/2。
因此,对于时间复杂度会随着输入数据的顺序、位置等不同而存在量级的差距的算法,我们在考量其时间复杂度的时候,需要从最好时间复杂度、最坏时间复杂度和平均时间复杂度等角度去分析,根据其具体的应用场景,做具体的衡量和评判。
空间复杂度
空间复杂度表示算法的存储空间与数据规模之间的增长关系,它的分析规则与时间复杂度的规则一致,也是只考虑高阶项,不要低阶项,也不要高阶项的系数。
算法在运行过程中占用的存储空间,主要包括:
输入/输出数据
算法本身
运行过程中额外需要的辅助空间
输入/输出数据占用的空间是必须的,算法本身的大小可以通过精简算法来缩减,但通常情况下,其缩减量对于算法缩减占用的存储空间的贡献量也比较小,因此算法在运行过程中需要的辅助变量占用的空间(即辅助空间)才是降低算法空间复杂度的关键。
void print(int n)
{
int[] a = new int[n];
for (int i = 0; i < n; ++i)
{
a[i] = i * i;
}
}
对于上述例子,忽略其低阶项和系数,其空间复杂度为 o ( n ) o(n) o(n)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。