第4章开始就不一一写出详细的概念了,具体还是要多看书掌握基础概念,很多时候之所以不理解都是因为基础知识没学好,概念没有深入地理解和认识才导致不能理解真正的含义。
最大子数组问题
大家应该都知道炒股吧(炒股的一般都经历过16年的股灾吧?如果你炒股没亏钱,那么你可以忽略我文章了继续炒股去吧)?简单地描述问题:我们怎样确定一个买入和卖出股票的日期,来使我们的股票收益最大化?
n天中有
C
n
2
C_{n}^{2}
Cn2种组合,那么组合的公式我们复习一下:
C
n
r
=
A
n
r
!
r
!
=
n
!
r
!
(
n
−
r
)
!
C_{n}^{r}=\frac{A_{n}^{r}!}{r!}=\frac{n!}{r!(n-r)!}
Cnr=r!Anr!=r!(n−r)!n!
精确地描述是:寻找A的和最大的非空连续子数组。
我们根据伪代码得到的递归式为T(n)=2T(n/2)+
Θ
\Theta
Θ(n)(n>1),可以用主方法来求解它的渐近时间复杂度。
矩阵乘法的Strassen算法
这章学到的是,渐近符号包含了常数因子,但递归符号(如T(n/2))并不包含。因此若一次矩阵加法花费了 Θ ( n 2 / 4 ) \Theta(n^{2}/4) Θ(n2/4)的时间,我们也可以说花费时间是 Θ ( n 2 ) \Theta(n^{2}) Θ(n2)。但是递归调用8次T(n/2)时间的花费是8T(n/2),这并不能省略地说花费了T(n/2)时间。如果省略的话,递归树就变为线性结构,而不是“茂盛的”了,树的每一层只为总和贡献了一项。所以说,要认清递归符号 T 和渐近符号 Θ \Theta Θ。
代入法
复习一下数学归纳法:
1.证明当n= 1时命题成立。
2.假设n=m时命题成立,那么可以推导出在n=m+1时命题也成立。(m代表任意自然数)
要注意的点是:
1.做出好的猜测。就是关于递归式的正确解尽可能做出比较接近真实解的猜测。猜不到就冇解了。
2.微妙的细节。有时猜出了正确的递归式解的渐近界,但在归纳证明时失败了。书上举的例子我还是暂时没办法那么深刻地理解,就是关于下面式子的归纳证明。
T
(
n
)
=
T
(
⌊
n
/
2
⌋
)
+
T
(
⌈
n
/
2
⌉
)
+
1
T(n)=T(\lfloor n/2 \rfloor )+T(\lceil n/2 \rceil )+1
T(n)=T(⌊n/2⌋)+T(⌈n/2⌉)+1
猜测T(n)=O(n)(0≤f(n)≤cg(n)渐近上界),尝试证明对某个恰当选出的常数c,T(n)≤cn成立。代入得到:
T
(
n
)
≤
c
⌊
n
/
2
⌋
+
c
⌈
n
/
2
⌉
+
1
=
c
n
+
1
T(n)≤c\lfloor n/2 \rfloor +c\lceil n/2 \rceil +1=cn+1
T(n)≤c⌊n/2⌋+c⌈n/2⌉+1=cn+1
为什么说并不意味着对任意c都有T(n)≤cn?(我觉得是因为c可能是负数所以才不会对任意c成立)。但事实上这个猜测是正确的。
3.避免陷阱。使用渐近符号很容易出错。
4.改变变量。可以通过改变变量将一个未知的递归式变成你熟悉的形式。
递归树
在递归树中,每个结点表示一个单一子问题的代价,子问题对应某递归函数调用。我们将树中每层中的代价求和,得到每层代价,然后将所有层的代价求和,得到所有层次的递归调用的总代价。
递归树一直递归到子问题规模为1。我们以下面的递归式为例子:
T
(
n
)
=
3
T
(
⌊
n
/
4
⌋
)
+
Θ
(
n
2
)
T(n)=3T(\lfloor n/4 \rfloor )+\Theta(n^{2})
T(n)=3T(⌊n/4⌋)+Θ(n2)
这个递归式一定要搞清楚他的含义:规模为n问题分解为3个子问题,每个子问题规模为n/4。3个子问题递归求解,每个花费T(n/4)时间。问题分解和子问题解合并的代价是
Θ
(
n
2
)
\Theta(n^{2})
Θ(n2)。
那么,递归树到最后一层的条件是什么呢?就是指问题按照1/4的方式分解,直到最后叶结点的问题规模为1,因此有n/
4
i
4^{i}
4i=1。 因为深度为i的结点对应规模为n/
4
i
4^{i}
4i的子问题。所以当n/
4
i
4^{i}
4i=1,即i=
l
o
g
4
n
log_{4}n
log4n。
主定理
这个定理对于理解算法复杂度非常重要,因此需要牢记!牢记!
令a≥1和b>1是常数,f(n)是一个函数,T(n)是定义在非负整数上的递归式:
T
(
n
)
=
a
T
(
n
/
b
)
+
f
(
n
)
T(n)=aT(n/b)+f(n)
T(n)=aT(n/b)+f(n)
其中我们将n/b解释为
⌊
n
/
b
⌋
或
⌈
n
/
b
⌉
\lfloor n/b \rfloor 或\lceil n/b \rceil
⌊n/b⌋或⌈n/b⌉ 。那么T(n)有如下渐近界:
1.若对某个常数
ε
>
0
\varepsilon>0
ε>0有
f
(
n
)
=
O
(
n
l
o
g
b
a
−
ε
)
f(n)=O(n^{log_{b}a-\varepsilon})
f(n)=O(nlogba−ε)(渐近上界),则
T
(
n
)
=
Θ
(
n
l
o
g
b
a
)
T(n)=\Theta(n^{log_{b}a})
T(n)=Θ(nlogba)。
2.若
f
(
n
)
=
Θ
(
n
l
o
g
b
a
)
f(n)=\Theta(n^{log_{b}a})
f(n)=Θ(nlogba),则
T
(
n
)
=
Θ
(
n
l
o
g
b
a
l
g
n
)
T(n)=\Theta(n^{log_{b}a}lgn)
T(n)=Θ(nlogbalgn)。
3.若对某个常数
ε
>
0
\varepsilon>0
ε>0有
f
(
n
)
=
Ω
(
n
l
o
g
b
a
+
ε
)
f(n)=\Omega(n^{log_{b}a+\varepsilon})
f(n)=Ω(nlogba+ε)(渐近下界),且对某个常数
c
<
1
c<1
c<1和所有足够大的n有
a
f
(
n
/
b
)
≤
c
f
(
n
)
af(n/b)≤cf(n)
af(n/b)≤cf(n),则
T
(
n
)
=
Θ
(
f
(
n
)
)
T(n)=\Theta(f(n))
T(n)=Θ(f(n))。
其实说白了,就是每次将函数
f
(
n
)
f(n)
f(n)和函数
n
l
o
g
b
a
n^{log_{b}a}
nlogba进行比较,两个函数的较大者决定了递归式的解。