在算法中,以频次最高的语句作为时间复杂度的度量标准。一般不必精确地计算出算法的时间复杂度,只要估计出相应的数量级即可,比如 O(1)、O(log2n)、O(n)、O(n2)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)
即 执行次数mmm是问题规模nnn的函数,O(f(n))O(f(n))O(f(n))表示nnn的时间复杂度。
算法的时间复杂度,一般与问题规模nnn有关;
1) 如果算法的时间复杂度与nnn无关,则
O(f(n))=O(1)O(f(n)) = O(1)O(f(n))=O(1)
2) 如果算法的时间复杂度与nnn为线性关系时,则
O(f(n))=O(n)O(f(n)) = O(n)O(f(n))=O(n)
3) 如果算法的时间复杂度与nnn为平方关系时,则
O(f(n))=O(n2)O(f(n)) = O(n^2)O(f(n))=O(n2);
4) 如果算法的时间复杂度与nnn为开方关系时,则
O(f(n))=O(n)O(f(n)) = O( \sqrt{n} )O(f(n))=O(n)
5) 如果算法的时间复杂度与nnn为对数关系时,则
O(f(n))=O(log2n)O(f(n)) = O(log_2n)O(f(n))=O(log2n)
6) 如果算法的时间复杂度与nnn成指数关系,则
O(f(n))=O(2n)O(f(n)) = O(2^n)O(f(n))=O(2n)
常用时间复杂度的大小关系如下:
O(1)≤O(log2n)≤O(n)≤O(nlog2n)≤O(n2)≤O(n3)≤⋯O(nk)≤O(2n)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)=an2+bn+c=O(an2)=O(n2)f(n) = an^2+bn+c = O(an^2) = O(n^2)f(n)=an2+bn+c=O(an2)=O(n2)
- f(n)=an+b=O(an)=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)=an2+blog2n=O(an2)=O(n2)f(n) = an^2+blog_2n = O(an^2) = O(n^2)f(n)=an2+blog2n=O(an2)=O(n2)
- f(n)=anlog2n+blog2n=O(anlog2n)=O(nlog2n)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)=anlog2n+blog2n=O(anlog2n)=O(nlog2n)f(n) = \\ \quad anlog_2n+blog_2n=O(anlog_2n)=O(nlog_2n)f(n)=anlog2n+blog2n=O(anlog2n)=O(nlog2n)
- f(n)=an2+bnlog2n=O(an2)=O(n2)f(n) = an^2+bnlog_2n=O(an^2)=O(n^2)f(n)=an2+bnlog2n=O(an2)=O(n2)
上式中,a、b、ca、b、ca、b、c都为常数,且a≠0a≠0a=0。
案例1.分析以下算法的复杂度
void func(int n){
int i=1,k=100;
while(i<n){
k++; i+=2;
}
}
解答:此算法的频繁语句是while{},设while{}语句执行的次数为mmm, 由题意知,iii从1开始, 每次递增2,最后取值为1+2m1+2m1+2m, 于是:
i=1+2m<ni=1+2m \lt ni=1+2m<n
即m<n−12=O(n−12)=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(n2)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(n2)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)2s=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<ns=m(m-1)/2 \lt ns=m(m−1)/2<n
则m≤nm \le \sqrt{n}m≤n
即该算法的时间复杂度为O(n)O(\sqrt{n})O(n)。

424

被折叠的 条评论
为什么被折叠?



