时间复杂度的详细求解

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

预备知识:

①积分近似:

∑ 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++)
		...

​ 用求和表示:
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++)
		...

​ 用求和表示:
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;
    ...
}

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;
    ...
}

​ 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这个方程就可以了!

### 决定时间复杂度的因素 影响算法时间复杂度的主要因素包括输入规模、基本操作的数量及其频率。对于不同类型的算法,这些因素的具体表现形式也有所不同。 #### 输入规模的影响 大多数情况下,随着输入数据量的增长,所需处理的工作量也会相应增加。例如,在排序算法中,待排序数组长度n直接影响到比较次数和交换次数[^1]。 #### 基本运的选择 不同的基础运具有各自的时间开销特性。比如加减乘除四则运是常数时间内完成的操作;而涉及查找表项或遍历列表等动作,则可能依赖于特定的数据结构设计而导致线性甚至更高级别的增长趋势[^2]。 #### 循环与递归的作用 当存在嵌套循环时,内部语句被执行的总频次会呈现指数级上升态势。同样地,如果函数调用自身形成递归关系,那么每次迭代都会带来额外的时间消耗,这取决于终止条件何时达成以及每层递归所做工作的多少[^4]。 ### 如何求解时间复杂度的方法 为了评估某个给定算法的时间效率,可以遵循如下几个通用原则来进行估: #### 大O表示法的应用 采用大O记号来描述渐近上界是最常见的做法之一。它只保留最高阶项并忽略系数,从而简化表达式以便直观理解整体变化规律。 #### 计各部分贡献 针对含有多个独立子过程的整体方案,分别考察各个组成部分对最终结果产生的影响权重,并累加以得出全局估计值。 #### 考虑边界情形 除了常规路径外,还需注意极端条件下(如最小/最大输入)的行为模式是否会引发异常高的成本支出,进而调整初始假设中的某些参数设定。 ```python def example_function(n): total = 0 for i in range(n): # O(n) for j in range(i, n): # O(n-i)=O(n), 整体为O(n^2) total += 1 return total # 总计:O(n^2)+O(1)=O(n^2) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值