结论:判断一个算法的效率时,操作数量中的常数项和其他次要项常常可以忽,只需要关注最高阶次项就能得出结论。
问题:如何用符号定性的判断算法的效率?
算法的复杂度(定性描述)
时间复杂度
算法运行后对时间需求量的定性描述
空间复杂度
算法运行后对空间需求量的定性描述
注意:数据结构课程重点关注的是算法的效率问题,因此,整个课程会集中于讨论算法的时间复杂度;但其使用的方法完全可以用于空间复杂度的判断。
大O表示法
算法效率严重依赖于操作(Operation)数量
操作数量的估算可以作为时间复杂度的估算
在判断时优先关注操作数量的最高次项
常见的时间复杂度
线性时间复杂度:O(n)
void func()
{
for (int i=0; i
{
// 复杂度为 O(1) 的程序语句
}
}
对数阶时间复杂度: O(logn)
void func()
{
int i = 1;
while (i < n) // 循环次数:log2n (2为底数)
{
// 复杂度为 O(1) 的程序语句
i *= 2;
}
}
平方阶时间复杂度: O(n2)
void func()
{
for (int i=0; i
{
for (int j=0; j
{
// 复杂度为 O(1) 的程序语句
}
}
}
时间复杂度计算练习
下面代码的时间复杂度是什么?
for (int i=0; i
{
for (int j=i; j
{
// 复杂度为 O(1) 的程序语句
}
}
i = 0 => n
i = 1 => n - 1
i = 2 => n - 2
...
i = n - 1 => 1
==> n + (n-1) + (n-2) + ... + 1 = n(n+1)/2
==> O(n(n+1)/2)
==> O(n2) (2为指数)
函数func()的时间复杂度是什么?
void t(int n) // O(n)
{
int i = 0;
while (i < n)
{
cout << i << endl;
}
}
void func(int n) // O(n(n+1)) => O(n2) (2为指数)
{
int i = 0;
while (i < n)
{
t(n) // O(n)
++i; // O(1)
}
}
函数 test() 的时间复杂度是什么?
void test(int n) // O(n + n2 + n3) ==> O(n3) (3为指数)
{
t(n); // O(n)
for (int i=0; i
t(i);
for (int i=0; i
for (int j=i; j
t(i);
}
小结
时间复杂度是算法运行时对于时间的需求量
大O表示法用于描述算法的时间复杂度
大O表示法只关注操作数量的最高次项
常见的时间复杂度为:线性阶,平方阶和对数阶
以上内容整理于狄泰软件学院系列课程,请大家保护原创!