第二版前言
这篇文章在 2022/10/7 重新进行了一些排版上的调整,最开始的原因是笔者认为这篇文章写的还算不错,而且里面涉及的知识以后可能还会用上,所以又传了一遍。
前言
Master 定理,又称主定理,用于程序的时间复杂度计算,核心思想是分治,近几年 Noip 常考时间复杂度的题目,都需要主定理进行运算。
前置
我们常见的程序时间复杂度有:
O(n)/O(n2)/O(nlog2n)/O(2n) 等等...
我们叫它程序的渐进时间复杂度,例如一段程序执行这样的循环:
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
sum+=a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
pai*=a[i][j];
显然,这段代码一共运行了 n3+2n2 次,我们将它的渐进时间复杂度写作 O(n3),即保留最高项但忽略其系数。
约定:一般我们将 log2n 写作 logn ,将 logn⋅logn 写作log2n
算时间复杂度有什么用呢?一般来说,在比赛时我们将知道程序的时间限制,一般为 1s ,我们可以通过粗略计算程序时间复杂度来判断程序是否能在 1s 通过,否则会 TLE(Time Limit Exceeded)。
时间复杂度 |
1s内稳过的范围 |
极限范围(危险) |
O(1) |
∞ |
∞ |
O(wys) |
∞ |
∞ |
O(logn) |
∞ |
∞ |
O(n) |
5×107 |
108 |
O(nlogn) |
5×105 |
106 |
O(n2) |
5000 |
10000 |
O(n3) |
300 |
500 |
O(2n) |
25 |
27 |
O(n!) |
11 |
11(稳过) |
O(nn) |
8 |
8(稳过) |
PS:由于程序存在常数因子,极限范围不一定能过,除非你是欧洲人。
大概来说,如果你算出的渐进时间复杂度量化后在千万级别[ n×107 ],基本上是很稳的
对于非递归程序时间复杂度的运算方法,比较简单粗暴的方法是数循环。但这种方法并不一定始终正确,如 NOIP2017PJT4 的二分答案是 O(logn) 复杂度的,dp 的转移是执行 n 次的,而对于单调队列,每个元素至多进队一次,出队一次,最多有 2n 次操作,dp 的总操作次数应该是将它们加在一起,共 3n 次操作,时间复杂度为 O(n),而不是 O(n2),总复杂度为 O(nlogn) ,与之类似的还有 kmp 算法的时间复杂度。(PS: kmp 算法的时间复杂度至今仍存在争议,我们一般将其视作 O(n) 的)
正文
介绍 master 定理前,首先要知道几个符号
- T(n) 表示时间复杂度,可以这样表示:T(n)=一个单项式,例如:
T(n)=2T(n/2)+f(n)
- Θ 读音:theta,表示等于
- O 读音:big oh,表示小于等于
- o 读音:small oh,表示小于
- Ω 读音:big omega,表示大于等于
- ω 读音:small omega,表示大于
主定理是怎么表示的呢?
- 我们目前有一个规模为n的问题
- 通过分治,我们将问题分成 a 个规模为 bn,每次递归将带来 f(n) 的额外计算
- 于是得到关系式:
T(n)=aT(bn)+f(n)
此外,我们还要定义一个 Ccrit,它是这样计算的:
Ccrit=logba
那么有:
1.
- 当 f(n)=O(nc),且 c<ccrit 时有:T(n)=Θ(nccrit)
- 例子:
- T(n)=8T(2n)+1000n2
- 此时 a=8,b=2,f(n)=1000n2
- 当 c=2 时,f(n)=O(n2)
- 又因为 Ccrit=logba=3>c
- 所以 T(n)=Θ(nlogba)=Θ(n3)
2.
- 当 f(n)=O(nc),且 c>ccrit 时有:T(n)=Θ(f(n))
- 例子:
- T(n)=2T(2n)+n2
- 此时 a=2,b=2,f(n)=n2
- 当 c=2 时,f(n)=O(n2)
- 又因为 ccrit=logba=1<c
- 所以 T(n)=Θ(f(n))=Θ(n2)
3.
- 若存在一个非负整数 k,使得 f(n)=Θ(nccritlogkn)
- 那么 T(n)=Θ(nccritlogk+1n)
- 例子:
- T(n)=2T(2n)+10n
- 此时 a=2,b=2,f(n)=10n;ccrit=logba=1
- 当 k=0 时 f(n)=Θ(n1log0n)=Θ(n)
- 所以 T(n)=Θ(n1log1n)=Θ(nlogn)
练手题
- 首先,我们知道 a=2,b=4,f(n)=n=n21;c=21,ccrit=log42=21
- 当 k=0 时,满足条件3,所以,T(n)=O(nlogn),选 C
T(n)
=T(n−1)+n−1+n
=T(n−2)+n−2+n−1+n
=...
=T(0)+0+1+2+...+n−2+n−1+n
=1+2n×(n+1)
=O(n2)
选择 D
- 假设 g(i),为计算 F(i) 的次数,因为 F(i)=F(i−1)+F(i−2) 所以 g(i)=g(i−1)+g(i−2)
- 因为 F(1)=g(1)=1,F(2)=g(2)=1,所以 g(n)=F(n)
- 则:
T(n)=g(n)=F(n)=O(F(n))
选择 D
完结
这和大家能够平安过初赛!