数据结构与算法 Big-O
前言
时间复杂度和空间复杂度常被用来评价一个算法的性能。解决一个问题有很多可能的算法。越好的算法消耗的资源越少。随着内存设备的更新,评价算法效率主要考虑时间复杂度。
常将算法性能常表示为:
- worst case
- average case
- almost never the best case
Big O notation是用于描述函数渐近行为的数学符号。更确切地说,它是用另一个(通常更简单的)函数来描述一个函数数量级的渐近上界。在数学中,它一般用来刻画被截断的无穷级数尤其是渐近级数的剩余项;在计算机科学中,它在分析算法复杂性的方面非常有用。
Big-O
定义:
Given a function T(N), we say T(N)=O(f(N)) if and only if there exist constants “c”, N0 >0 such that every N>=N0 ,T(N)<=cf(N).
证明方法:
假设比较如下两个方程,找到C, N0的值使得当N>=N0时满足50N+99<=CN2
- T(N)=50N+99
- f(N)=N2
方法1:假设c=1,得到break-even point(N0)
从图中可以看出,尽管 T(N) 开始时大于f(N),但存在一个交点( break-even point ),当超过该点时 f(N) 将始终比T(N)更大。 这是找到 N0 的一种可能方法。
根
据
B
i
g
−
O
定
义
:
T
(
N
)
<
=
c
f
(
N
)
,
假
设
c
=
1
来
找
到
b
r
e
a
k
−
e
v
e
n
−
p
o
i
n
t
根据Big-O定义: T(N)<=cf(N) ,假设c=1 来找到break-even-point
根据Big−O定义:T(N)<=cf(N),假设c=1来找到break−even−point
得
到
:
50
N
+
99
<
=
(
1
)
N
2
得到: {50N+99<=(1)N^2 }
得到:50N+99<=(1)N2
可
写
成
:
N
2
−
50
N
−
99
>
=
0
可写成:{N^2-50N-99>=0}
可写成:N2−50N−99>=0
根
据
一
元
二
次
不
等
式
得
到
:
50
±
5
0
2
+
4
(
1
)
(
99
)
2
(
1
)
根据一元二次不等式得到: \frac{50\pm\sqrt{50^2 + 4(1) (99)\quad}} {2(1)}
根据一元二次不等式得到:2(1)50±502+4(1)(99)
N
0
=
50
+
2896
2
≈
52
(
根
据
定
义
N
0
>
0
)
{N{_0}} = \frac{50+\sqrt{2896}\quad} {2}\approx52(根据定义{N{_0}}>0)
N0=250+2896≈52(根据定义N0>0)
得
到
当
常
数
c
等
于
1
,
N
0
等
于
52
或
大
于
52
均
满
足
B
i
g
−
O
定
义
得到当常数 c等于1,{N{_0}}等于52 或大于52均满足Big-O定义
得到当常数c等于1,N0等于52或大于52均满足Big−O定义
方法2:假设N0 ,导出不等式,得到常数c
50
N
+
99
=
50
N
(
1
)
+
99
(
1
)
2
(
k
e
y
s
t
e
p
)
50N+99 = 50N(1) +99(1)^2 (key step)
50N+99=50N(1)+99(1)2(keystep)
<
=
50
N
(
N
)
+
99
(
1
)
2
(
因
为
N
>
=
1
)
<=50N(N)+99(1)^2 (因为N>=1)
<=50N(N)+99(1)2(因为N>=1)
<
=
50
N
(
N
)
+
99
(
N
)
2
(
因
为
N
>
=
1
)
<=50N(N) +99(N)^2 (因为N>=1)
<=50N(N)+99(N)2(因为N>=1)
=
149
N
2
=149N^2
=149N2
得
到
当
常
数
C
等
于
149
,
N
0
等
于
1
时
满
足
B
i
g
−
O
定
义
得到当常数C等于149,N_0 等于1时满足Big-O定义
得到当常数C等于149,N0等于1时满足Big−O定义
基本定理
1.N 的幂按其指数排序 (Na=O(Nb) 当且仅当a<=b)。 例如:N2 可等于O(N3), 但N3 不等于O(N2)
The powers of N are ordered according to their exponents.
2.对数的增长速度比 N 的任何其他正幂都慢。 例如:log2 N=O(N1/2)
A logarithm grows more slowly than any other positive power of N.
L’Hopital’s Rule
3.如果f(N)=O(g(N)) 并且g(N)=O(h(N)) 则 f(N)=O(h(N))。
4.f(N)+g(N)=O(max( f(N), g(N))。 例如:O(N2 +N +1)=O(N2)
5.如果f1(N)=O(g1(N)) 并且f2(N)=O(g2(N)) 则 f1(N) x f2(N)=O(g1(N) x g2(N))。
6.对于任意大于0的整数C来说,Cf(N)=O(f(N))。 例如:O(100N)=O(N)
确定一个算法的时间复杂度
例题1:
以下方代码为例:
bool uniqueElements(vector<int>& A){
for i from 0 to N-1:
for j from 0 to i-1:
if A[i]=A[j] then
return false
return true
}
- 首先找到算法中最频繁被运行的代码
if A[i]=A[j]
if A[i]=A[j]
存在于两层循环中,外层循环运行N-1次内层循环则是由外层循环的迭代变量i
所决定- 下表纵轴为 i 的迭代,横轴为 j 的迭代,阴影区域的格子数量为两层循环中
if A[i]=A[j] then
被运行的次数=(N2 -N)/2 (总共N*N个格子减去对角线的格子并除以二)
return true
的时间复杂度为O(1)- 最终得到T(N)=O(N2)+O(1)
- 根据Big-O基本定理得到:T(N)=O(N2)
例题2:
bool uniqueElements(vector<int>& A){
mergeSort(A)
for i from 1 to N-1:
if A[i-1] =A[i] then
return false
return true
}
- 在此题中
mergeSort(A)
的时间复杂度为O(NlogN) - 循环的时间复杂度O(N)
return true
的时间复杂度为O(1)- 最终得到T(N)=O(NlogN)+O(N)+O(1)
- 根据Big-O基本定理得到:T(N)=O(NlogN)