3.2 函数的增长
大O表示法定义:
当
x
>
k
时
,
∣
f
(
x
)
∣
<
=
C
∣
g
(
x
)
∣
,
C
∣
g
(
x
)
|
就
记
做
O
(
g
(
x
)
)
当 x > k 时,|f(x)|<=C|g(x)|,C|g(x)|就记做\ O(g(x))
当x>k时,∣f(x)∣<=C∣g(x)∣,C∣g(x)|就记做 O(g(x))
这个其实很简单,分为2个部分取考虑:
f(x)
是什么,即代码会执行多少次。
例1:
// $n=100;
for($i=1;$i<=$n;$i++){
print "当前i的值是:".$i.PHP_EOL;
}
问,上面这个函数执行多少次?答:1+3*n
。$i=1
是1,$i<=$n
,$i++
,print print "当前i的值是:".$i.PHP_EOL;
各会执行n次,所以总次数为1+3*n
次,即f(x)=1+3*n
。
然后考虑,当n趋紧于无限大的时候,+1和*3
对n的值影响到不大,所以大O表示法就可以写成
f
(
x
)
=
1
+
3
x
=
O
(
x
)
或
者
用
更
加
习
惯
的
n
来
替
代
x
O
(
n
)
f(x)=1+3x=O(x) \\ 或者用更加习惯的n来替代x \\ O(n)
f(x)=1+3x=O(x)或者用更加习惯的n来替代xO(n)
例2:
for($i=1;$i<=$n;$i++){
for($j=1;$j<=$n;$j++){
print "当前i和j的值为:({$i},{$j})".PHP_EOL;
}
}
例2中,函数执行了多少次?n*(3*n+1)+2*n+1
,计算后得到结果:
3
n
2
+
3
n
+
1
3{n}^{2}+3n+1
3n2+3n+1
然后我们设想,n的平方的增加速度会比3n快很多,当n趋近于无限大的时候,上面的函数起主要作用的就是n的平方。
f
(
x
)
=
3
n
2
+
3
n
+
1
=
O
(
n
2
)
f(x)=3{n}^{2}+3n+1=O({n}^{2})
f(x)=3n2+3n+1=O(n2)
上面这两个例子可以总结成下面的这个定理:
f
(
x
)
=
a
n
x
n
+
a
n
−
1
x
n
−
1
+
a
n
−
2
x
n
−
2
⋯
+
a
1
x
1
+
a
0
x
0
a
n
∈
Q
,
f
(
x
)
=
Q
(
x
n
)
f(x)={a}_{n}{x}^{n}+{a}_{n-1}{x}^{n-1}+{a}_{n-2}{x}^{n-2} \cdots + {a}_{1}{x}^{1}+ {a}_{0}{x}^{0} \\ {a}_{n} \in Q,\\ f(x)=Q({x}^{n})
f(x)=anxn+an−1xn−1+an−2xn−2⋯+a1x1+a0x0an∈Q,f(x)=Q(xn)
证明过程:
x
>
=
1
时
∣
f
(
x
)
∣
=
∣
a
n
x
n
+
a
n
−
1
x
n
−
1
+
a
n
−
2
x
n
−
2
⋯
+
a
1
x
1
+
a
0
x
0
∣
<
=
∣
a
n
∣
x
n
+
∣
a
n
−
1
∣
x
n
−
1
+
∣
a
n
−
2
∣
x
n
−
2
⋯
+
∣
a
1
∣
x
1
+
∣
a
0
∣
x
0
=
x
n
(
a
n
+
a
n
−
1
×
1
x
+
a
n
−
2
×
1
x
2
⋯
+
a
1
×
1
x
n
−
1
+
a
n
×
1
x
n
)
<
=
x
n
(
a
n
+
a
n
−
1
+
a
n
−
2
⋯
a
1
+
a
0
)
即
∣
f
(
x
)
∣
<
=
C
∣
g
(
x
)
∣
,
g
(
x
)
=
x
n
,
即
f
(
x
)
=
O
(
x
n
)
x>=1时\\ |f(x)|=|{a}_{n}{x}^{n}+{a}_{n-1}{x}^{n-1}+{a}_{n-2}{x}^{n-2} \cdots + {a}_{1}{x}^{1}+ {a}_{0}{x}^{0}| \\ <=|{a}_{n}|{x}^{n}+|{a}_{n-1}|{x}^{n-1}+|{a}_{n-2}|{x}^{n-2} \cdots + |{a}_{1}|{x}^{1}+ |{a}_{0}|{x}^{0} \\ = {x}^{n}({a}_{n}+{a}_{n-1} \times \frac{1}{x} +{a}_{n-2} \times \frac{1}{{x}^{2}} \cdots +{a}_{1} \times \frac{1}{{x}^{n-1}} +{a}_{n} \times \frac{1}{{x}^{n}}) \\ <= {x}^{n}({a}_{n}+{a}_{n-1}+{a}_{n-2} \cdots {a}_{1}+{a}_{0}) \\ 即 |f(x)|<=C|g(x)|,g(x)={x}^{n},即 f(x)=O({x}^{n})
x>=1时∣f(x)∣=∣anxn+an−1xn−1+an−2xn−2⋯+a1x1+a0x0∣<=∣an∣xn+∣an−1∣xn−1+∣an−2∣xn−2⋯+∣a1∣x1+∣a0∣x0=xn(an+an−1×x1+an−2×x21⋯+a1×xn−11+an×xn1)<=xn(an+an−1+an−2⋯a1+a0)即∣f(x)∣<=C∣g(x)∣,g(x)=xn,即f(x)=O(xn)
至于这里为什么要x>1,是因为执行步骤肯定是存在的,如果没有执行步骤,那么讨论算法复杂度就没有意义了。
函数组合的增长
相加:
如
果
,
f
1
=
O
(
g
1
(
x
)
)
,
f
2
=
O
(
g
2
(
x
)
)
,
则
(
f
1
+
f
2
)
(
x
)
=
O
(
g
(
x
)
)
,
g
(
x
)
=
m
a
x
(
g
1
(
x
)
,
g
2
(
x
)
)
如果,{f}_{1}=O({g}_{1}(x)),{f}_{2}=O({g}_{2}(x)),\\则({f}_{1}+{f}_{2})(x)=O(g(x)),g(x)=max({g}_{1}(x),{g}_{2}(x))
如果,f1=O(g1(x)),f2=O(g2(x)),则(f1+f2)(x)=O(g(x)),g(x)=max(g1(x),g2(x))
相乘:
如
果
,
f
1
=
O
(
g
1
(
x
)
)
,
f
2
=
O
(
g
2
(
x
)
)
,
则
(
f
1
f
2
)
(
x
)
=
O
(
g
(
x
)
)
,
g
(
x
)
=
(
g
1
(
x
)
g
2
(
x
)
)
如果,{f}_{1}=O({g}_{1}(x)),{f}_{2}=O({g}_{2}(x)),\\则({f}_{1}{f}_{2})(x)=O(g(x)),g(x)=({g}_{1}(x){g}_{2}(x))
如果,f1=O(g1(x)),f2=O(g2(x)),则(f1f2)(x)=O(g(x)),g(x)=(g1(x)g2(x))
函数执行的下限:大欧米伽表示法
当 x > k 时 , ∣ f ( x ) ∣ > = C ∣ g ( x ) ∣ , C ∣ g ( x ) | 就 记 做 Ω ( g ( x ) ) 当 x > k 时,|f(x)|>=C|g(x)|,C|g(x)|就记做\ \Omega(g(x)) 当x>k时,∣f(x)∣>=C∣g(x)∣,C∣g(x)|就记做 Ω(g(x))
上面是考虑x趋于无限大,这里则不是,具体根据定义来推倒吧,或者可以说是算法的一般情况。
当函数的大O表示法和大欧米伽相同时:大西塔
f ( x ) = O ( g ( x ) ) , f ( x ) = Ω ( g ( x ) ) , 则 f ( x ) = Θ ( g ( x ) ) f(x)=O(g(x)),f(x)=\Omega(g(x)),则 f(x)= \Theta (g(x)) f(x)=O(g(x)),f(x)=Ω(g(x)),则f(x)=Θ(g(x))