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