在算法中,以频次最高的语句作为时间复杂度的度量标准。一般不必精确地计算出算法的时间复杂度,只要估计出相应的数量级即可,比如
O
(
1
)
、
O
(
l
o
g
2
n
)
、
O
(
n
)
、
O
(
n
2
)
O(1)、O(log_2n)、O(n)、O(n^2)
O(1)、O(log2n)、O(n)、O(n2) 等
设m为频繁语句(也叫循环语句,或者递归语句)执行的次数,n为问题的规模,则
m
=
O
(
f
(
n
)
)
=
O
(
n
)
m=O(f(n)) = O(n)
m=O(f(n))=O(n)
即 执行次数
m
m
m是问题规模
n
n
n的函数,
O
(
f
(
n
)
)
O(f(n))
O(f(n))表示
n
n
n的时间复杂度。
算法的时间复杂度,一般与问题规模
n
n
n有关;
1) 如果算法的时间复杂度与
n
n
n无关,则
O
(
f
(
n
)
)
=
O
(
1
)
O(f(n)) = O(1)
O(f(n))=O(1)
2) 如果算法的时间复杂度与
n
n
n为线性关系时,则
O
(
f
(
n
)
)
=
O
(
n
)
O(f(n)) = O(n)
O(f(n))=O(n)
3) 如果算法的时间复杂度与
n
n
n为平方关系时,则
O
(
f
(
n
)
)
=
O
(
n
2
)
O(f(n)) = O(n^2)
O(f(n))=O(n2);
4) 如果算法的时间复杂度与
n
n
n为开方关系时,则
O
(
f
(
n
)
)
=
O
(
n
)
O(f(n)) = O( \sqrt{n} )
O(f(n))=O(n)
5) 如果算法的时间复杂度与
n
n
n为对数关系时,则
O
(
f
(
n
)
)
=
O
(
l
o
g
2
n
)
O(f(n)) = O(log_2n)
O(f(n))=O(log2n)
6) 如果算法的时间复杂度与
n
n
n成指数关系,则
O
(
f
(
n
)
)
=
O
(
2
n
)
O(f(n)) = O(2^n)
O(f(n))=O(2n)
常用时间复杂度的大小关系如下:
O
(
1
)
≤
O
(
l
o
g
2
n
)
≤
O
(
n
)
≤
O
(
n
l
o
g
2
n
)
≤
O
(
n
2
)
≤
O
(
n
3
)
≤
⋯
O
(
n
k
)
≤
O
(
2
n
)
O(1) \le O(log_2n) \le O(n) \le O(nlog_2n) \le O(n^2) \le O(n^3) \le \cdots O(n^k) \le O(2^n)
O(1)≤O(log2n)≤O(n)≤O(nlog2n)≤O(n2)≤O(n3)≤⋯O(nk)≤O(2n)
估算公式:
- f ( n ) = a n 2 + b n + c = O ( a n 2 ) = O ( n 2 ) f(n) = an^2+bn+c = O(an^2) = O(n^2) f(n)=an2+bn+c=O(an2)=O(n2)
- f ( n ) = a n + b = O ( a n ) = O ( n ) f(n) = an+b = O(an) = O(n) f(n)=an+b=O(an)=O(n)
- f ( n ) = c = O ( c ) = O ( 1 ) f(n) = c = O(c) = O(1) f(n)=c=O(c)=O(1)
- f ( n ) = a n 2 + b l o g 2 n = O ( a n 2 ) = O ( n 2 ) f(n) = an^2+blog_2n = O(an^2) = O(n^2) f(n)=an2+blog2n=O(an2)=O(n2)
- f ( n ) = a n l o g 2 n + b l o g 2 n = O ( a n l o g 2 n ) = O ( n l o g 2 n ) f(n) = an^{log_2n}+blog_2n = O(an^{log_2n})=O(n^{log_2n}) f(n)=anlog2n+blog2n=O(anlog2n)=O(nlog2n)
- f ( n ) = a n l o g 2 n + b l o g 2 n = O ( a n l o g 2 n ) = O ( n l o g 2 n ) f(n) = \\ \quad anlog_2n+blog_2n=O(anlog_2n)=O(nlog_2n) f(n)=anlog2n+blog2n=O(anlog2n)=O(nlog2n)
-
f
(
n
)
=
a
n
2
+
b
n
l
o
g
2
n
=
O
(
a
n
2
)
=
O
(
n
2
)
f(n) = an^2+bnlog_2n=O(an^2)=O(n^2)
f(n)=an2+bnlog2n=O(an2)=O(n2)
上式中, a 、 b 、 c a、b、c a、b、c都为常数,且 a ≠ 0 a≠0 a=0。
案例1.分析以下算法的复杂度
void func(int n){
int i=1,k=100;
while(i<n){
k++; i+=2;
}
}
解答:此算法的频繁语句是while{},设while{}语句执行的次数为
m
m
m, 由题意知,
i
i
i从1开始, 每次递增2,最后取值为
1
+
2
m
1+2m
1+2m, 于是:
i
=
1
+
2
m
<
n
i=1+2m \lt n
i=1+2m<n
即
m
<
n
−
1
2
=
O
(
n
−
1
2
)
=
O
(
n
)
m \lt \frac{n-1}{2} =O(\frac{n-1}{2}) =O(n)
m<2n−1=O(2n−1)=O(n)
所以,该算法的时间复杂度为
O
(
n
)
O(n)
O(n)。
案例2. 分析以下算法的时间复杂度
void func(int n){
int i,j,x=0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
x++;
}
解答:该算法的频繁语句是x++; 设x++执行的次数为m, 则
\begin{align}
m & = \sum_{i=1}^{n-1} \sum_{j=i+1}^n1 \
&= \sum_{i=1}^{n-1}(n-(i+1)+1) \
&= \sum_{i=1}^{n-1}(n-i) \
&= (n-1)+(n-2)+ \cdots + 1 \
&= \frac{(n-1)((n-1)+1))}{2}=\frac{n(n-1)}{2}
\end{align}
即
m
=
n
(
n
−
1
)
2
=
O
(
n
(
n
−
1
)
2
)
=
O
(
n
2
)
m=\frac{n(n-1)}{2} =O(\frac{n(n-1)}{2}) =O(n^2)
m=2n(n−1)=O(2n(n−1))=O(n2)
所以,该算法的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)。
案例3. 分析以下程序段的时间复杂度
void func(int n){
int i=0,s=0;
while(s<n){
i++;
s = s+i;
}
}
解答:该算法的频繁语句为while{}, 设while{}的执行次数为m, i从0开始递增1,直到m-1为止,有
s
=
0
+
1
+
2
+
⋯
+
(
m
−
1
)
=
m
(
m
−
1
)
2
s=0+1+2+ \cdots +(m-1) =\frac{m(m-1)}{2}
s=0+1+2+⋯+(m−1)=2m(m−1)
又
s
=
m
(
m
−
1
)
/
2
<
n
s=m(m-1)/2 \lt n
s=m(m−1)/2<n
则
m
≤
n
m \le \sqrt{n}
m≤n
即该算法的时间复杂度为
O
(
n
)
O(\sqrt{n})
O(n)。