当前位置:   article > 正文

时间复杂度的详细求解_时间复杂度怎么算

时间复杂度怎么算

时间复杂度计算方法(包括递归式求解)

预备知识:

①积分近似:

∑ i = 0 n f ( i ) ∼ ∫ i = 0 i = n f ( i ) d i \sum_{i=0}^nf(i)\sim\int_{i=0}^{i=n}f(i) di i=0nf(i)i=0i=nf(i)di

​ 一般地:
∑ i = 0 n f ( i ) ≤ ∫ i = 0 i = n f ( i ) d i \sum_{i=0}^nf(i)\le\int_{i=0}^{i=n}f(i) di i=0nf(i)i=0i=nf(i)di

②分治递归式通解:(主定理的原式)

T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)

​ 通解为:
T ( n ) = n log ⁡ b a T ( 1 ) + ∑ i = 0 ⌈ log ⁡ b n ⌉ a i f ( n / b i ) T(n)=n^{\log_ba}T(1)+\sum_{i=0}^{\lceil\log_bn\rceil}a^if(n/b^i) T(n)=nlogbaT(1)+i=0logbnaif(n/bi)

​ 其中 ⌈ log ⁡ b n ⌉ = log ⁡ b n − 1 \lceil\log_bn\rceil=\log_bn-1 logbn=logbn1,求和部分直接用积分近似计算即可

③衡量算法效率参数
衡量算法效率参数数学语言表示
O O O f ( n ) ≤ c g ( n ) f(n)\le cg(n) f(n)cg(n) O ( g ( n ) ) O(g(n)) O(g(n))
Θ \Theta Θ c 1 g ( n ) ≤ f ( n ) ≤ c 2 g ( n ) c_1g(n)\le f(n)\le c_2g(n) c1g(n)f(n)c2g(n) Θ ( g ( n ) ) \Theta(g(n)) Θ(g(n))
Ω \Omega Ω f ( n ) ≥ c g ( n ) f(n)\ge cg(n) f(n)cg(n) Ω ( g ( n ) ) \Omega(g(n)) Ω(g(n))
近似法 lim ⁡ i → 0 = f ( n ) / g ( n ) = 1 \lim_{i\to0}=f(n)/g(n)=1 limi0=f(n)/g(n)=1 ∼ g ( n ) \sim g(n) g(n)

其中大 O O O法和大 Ω \Omega Ω法,常用于时间复杂度的标度。一般来说,时间复杂度用 O O O

for循环

①循环嵌套,变量间无关联
for(int i = 0; i < n; i++)
	for(int j = 0; j < n; j++)
		...
  • 1
  • 2
  • 3

​ 用求和表示:
T ( n ) = ∑ i = 0 n − 1 ∑ j = 0 n − 1 1 T(n)=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}1 T(n)=i=0n1j=0n11
​ 计算时间复杂度:

​ 法①:
T ( n ) = ∑ i = 0 n − 1 ∑ j = 0 n − 1 1 = ∑ i = 0 n − 1 ( n − 1 − 0 + 1 ) = n ∑ i = 0 n − 1 1 = n 2 T(n)=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}1=\sum_{i=0}^{n-1}(n-1-0+1)=n\sum_{i=0}^{n-1}1=n^2 T(n)=i=0n1j=0n11=i=0n1(n10+1)=ni=0n11=n2
​ 法②:
T ( n ) = ∑ i = 0 n − 1 ∑ j = 0 n − 1 1 ∼ ∬ d i d j = ∫ i = 0 i = n − 1 d i ∫ j = 0 j = n − 1 d j = n 2 T(n)=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}1\sim\iint didj=\int_{i=0}^{i=n-1}di\int_{j=0}^{j=n-1}dj=n^2 T(n)=i=0n1j=0n11didj=i=0i=n1dij=0j=n1dj=n2
​ 故时间复杂度为 O ( n 2 ) O(n^2) O(n2)

②嵌套循环,变量间有关联
for(int i = 0; i < n; i++)
	for(int j = i + 1; j < n; j++)
		...
  • 1
  • 2
  • 3

​ 用求和表示:
T ( n ) = ∑ i = 0 n − 1 ∑ j = i + 1 n − 1 1 T(n)=\sum_{i=0}^{n-1}\sum_{j=i+1}^{n-1}1 T(n)=i=0n1j=i+1n11
​ 计算时间复杂度

​ 法①:
T ( n ) = ∑ i = 0 n − 1 ∑ j = i + 1 n − 1 1 = ∑ i = 0 n − 1 ( n − i − 1 ) = n 2 / 2 − n / 2 ∼ n 2 T(n)=\sum_{i=0}^{n-1}\sum_{j=i+1}^{n-1}1=\sum_{i=0}^{n-1}(n-i-1)=n^2/2-n/2\sim n^2 T(n)=i=0n1j=i+1n11=i=0n1(ni1)=n2/2n/2n2
​ 法②:
T ( n ) = ∑ i = 0 n − 1 ∑ j = i + 1 n − 1 1 ∼ ∬ d i d j = ∫ i = 0 i = n − 1 d i ∫ j = i + 1 j = n − 1 d j = ∫ i = 0 i = n − 1 ( n − i − 1 ) d i = n 2 − i 2 2 ∣ 0 n − 1 − n = n 2 / 2 − 1 / 2 ∼ n 2 T(n)=\sum_{i=0}^{n-1}\sum_{j=i+1}^{n-1}1\sim\iint didj=\int_{i=0}^{i=n-1}di\int_{j=i+1}^{j=n-1}dj=\int_{i=0}^{i=n-1}(n-i-1)di=n^2-\frac{i^2}{2}|_0^{n-1}-n\\ =n^2/2-1/2\sim n^2 T(n)=i=0n1j=i+1n11didj=i=0i=n1dij=i+1j=n1dj=i=0i=n1(ni1)di=n22i20n1n=n2/21/2n2
​ 在这里可以发现积分的结果一般比离散求和要大,这保证了时间上界,所以积分近似有效且高效。

​ 故时间复杂度为 O ( n 2 ) O(n^2) O(n2)

while循环(假设 i i i从1开始变化)

①条件变量呈线性变化

​ 直接用for循环的方法即可,但如果增量不为1的话:

while(i <= n){
	i += 2;
    ...
}
  • 1
  • 2
  • 3
  • 4

i i i的变化看作是等差数列
1   3   5   . . .   n 1\ 3\ 5\ ...\ n 1 3 5 ... n
​ 那么上述数列有多少项数,那么耗时就为多少:

​ 先写出数列的递归表达式:
x ( k ) = x ( k − 1 ) + 2 x(k)=x(k-1)+2 x(k)=x(k1)+2
​ 计算得出:
x ( k ) = 2 k − 1 x(k)=2k-1 x(k)=2k1
​ 令 x ( k ) = n x(k)=n x(k)=n,这个时候 k = T ( n ) k=T(n) k=T(n)
T ( n ) = k = n + 1 2 ∼ O ( n ) T(n)=k=\frac{n+1}{2}\sim O(n) T(n)=k=2n+1O(n)
​ 时间复杂度为 O ( n ) O(n) O(n)

②条件变量呈k次变化
while(i <= n){    
	i *= 2;
    ...
}
  • 1
  • 2
  • 3
  • 4

​ i变量每次乘以2,同样也可以看作求和,但这个时候 i i i的变化为等比数列:
1   2   4   . . .   n 1\ 2\ 4\ ...\ n 1 2 4 ... n

​ 同样的,令数列:
x ( k ) = 2   x ( k − 1 ) x(k)=2\ x(k-1) x(k)=2 x(k1)

​ 计算得出:
x ( k ) = 2 k − 1 x(k)=2^{k-1} x(k)=2k1
​ 令 x ( k ) = n x(k)=n x(k)=n,这个时候 k = T ( n ) k=T(n) k=T(n)
T ( n ) = k = log ⁡ n + 1 ∼ O ( log ⁡ n ) T(n)=k=\log n+1\sim O(\log n) T(n)=k=logn+1O(logn)
​ 时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

递归式求解

对于递归式,只要求出方程就可以了,一般来说难度不大,下面介绍典型递归式。

变量线性递归

形如
T ( n ) = a T ( n − b ) + f ( n ) T(n)=aT(n-b)+f(n) T(n)=aT(nb)+f(n)
一般采用数列不动点求出方程

比如
T ( n ) = T ( n − 1 ) + n T(n)=T(n-1)+n T(n)=T(n1)+n
求得
T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)
比如
T ( n ) = 2 T ( n − 1 ) + n T(n)=2T(n-1)+n T(n)=2T(n1)+n
求得数列不动点 x = − n x=-n x=n,构造:
T ( n ) − x = 2 T ( n − 1 ) + n − x T(n)-x=2T(n-1)+n-x T(n)x=2T(n1)+nx
不难得到:
T ( n ) + n = 2 [ T ( n − 1 ) + n ] T(n)+n=2[T(n-1)+n] T(n)+n=2[T(n1)+n]
求得:
T ( n ) = O ( 2 n ) T(n)=O(2^n) T(n)=O(2n)

什么是数列不动点?

对于一阶线性递推数列:
x n = p x n − 1 + q x_n=px_{n-1}+q xn=pxn1+q
x n = x n − 1 = x x_n=x_{n-1}=x xn=xn1=x,这个 x x x就是不动点:
x = q 1 − p x=\frac{q}{1-p} x=1pq
因此:
x n − x = p x n − 1 + q − x x_n-x=px_{n-1}+q-x xnx=pxn1+qx
化简得到:
x n − q 1 − p = p ( x n − 1 − q 1 − p ) x_n-\frac{q}{1-p}=p(x_{n-1}-\frac{q}{1-p}) xn1pq=p(xn11pq)

分治递归

T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)

​ 通解为:
T ( n ) = n log ⁡ b a T ( 1 ) + ∑ i = 0 ⌈ log ⁡ b n ⌉ a i f ( n / b i ) T(n)=n^{\log_ba}T(1)+\sum_{i=0}^{\lceil\log_bn\rceil}a^if(n/b^i) T(n)=nlogbaT(1)+i=0logbnaif(n/bi)

​ 其中 ⌈ log ⁡ b n ⌉ = log ⁡ b n − 1 \lceil\log_bn\rceil=\log_bn-1 logbn=logbn1,求和部分直接用积分近似计算即可

总结

​ 时间复杂度不难分析,只需要观察代码,然后分析是啥变量在变化,条件是啥。然后用数列表示出这个变量,那么这个数列的项数就是 时间函数,求出时间函数一切都好办辣!

​ 对于增量不为1的情况,还是构造数列 x ( k ) x(k) x(k),解出 x ( T ( n ) ) = n x(T(n))=n x(T(n))=n这个方程就可以了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/529970
推荐阅读
相关标签
  

闽ICP备14008679号