算法导论 4 Problems 答案

4-1

a

a=2,b=2,f(n)=n3,logba=1

因此根据第三个条件,可以构造出 c=18,最终 T(n)=Θ(n3)

b

a=1,b=118,f(n)=n,logba=0

因此根据第三个条件,可以构造出 c=811,最终 T(n)=Θ(n)

c

a=16,b=4,f(n)=n2,logba=2

因此根据第二个条件,得到 k=0,最终 T(n)=Θ(n2lgn)

d

a=4,b=2,f(n)=n2lgn,logba=2

因此根据第二个条件,得到 k=1,最终 T(n)=Θ(n2lg2n)

e

a=8,b=3,f(n)=n2,logba=log38<2

因此根据第三个条件,可以构造出 c=89,最终 T(n)=Θ(n2)

f

a=7,b=2,f(n)=n2lgn,logba=log27>2

因此根据第一个条件,T(n)=Θ(nlg7)

g

a=2,b=4,f(n)=n,logba=log42=12

因此根据第二个条件,得到 k=0,最终 T(n)=Θ(nlgn)

h

m=nmod2,可以知道,m{0,1}

那么有:

T(n)=k=0n/2(2k+m)2=k=0n/2(4k2+4km+m2)=m2n2+k=0n/2(4k2+4km)=m2n2+4k=0n/2k2+4mk=0n/2k=m2n2+4n/2(n/2+1)(n+1)6+4mn/2(n/2+1)2=Θ(n3)

4-2

Ta1(N,n)=Ta1(N,n/2)+Θ(1)Ta2(N,n)=Ta2(N,n/2)+Θ(N)Ta3(N,n)=Ta3(N,n/2)+Θ(n)Tb1(N,n)=2Tb1(N,n/2)+Θ(1)+Θ(n)Tb2(N,n)=2Tb2(N,n/2)+Θ(N)Tb3(N,n)=2Tb3(N,n/2)+Θ(n)Tc1(N,n)=8Tc1(N,n/2)+Θ(1)Tc2(N,n)=8Tc2(N,n/2)+Θ(N2)Tc3(N,n)=8Tc3(N,n/2)+Θ(n2)

Ta1:a=1,b=2,f(n)=Θ(1),logba=0。因此根据第二个条件,得到 k=0,最终 Ta1(N,n)=Θ(lgn)

Ta2(N,n)=Ta2(N,n/2)+Θ(N)=Ta2(N,n/4)+Θ(N)+Θ(N)=Ta2(N,n/8)+Θ(N)+Θ(N)+Θ(N)=i=0lgn1Θ(N)=Θ(Nlgn)

Ta3:a=1,b=2,f(n)=Θ(n),logba=0。因此根据第三个条件,可以构造出 c=12,最终 Ta3(N,n)=Θ(n)

Tb1:a=2,b=2,f(n)=Θ(n),logba=1。因此根据第二个条件,得到 k=0,最终 Tb1(N,n)=Θ(nlgn)

Tb2(N,n)=2Tb2(N,n/2)+Θ(N)=4Ta2(N,n/4)+2Θ(N)+Θ(N)=8Ta2(N,n/8)+4Θ(N)+2Θ(N)+Θ(N)=i=0lgn12iΘ(N)=Θ(Nn)

Tb3:Tb3(N,n)=Tb1(N,n)=Θ(nlgn)

Tc1:a=8,b=2,f(n)=Θ(1),logba=3。因此根据第一个条件,Tc1(N,n)=Θ(n3)

Tc2(N,n)=8Tc2(N,n/2)+Θ(N2)=64Ta2(N,n/4)+8Θ(N)+Θ(N)=512Ta2(N,n/8)+64Θ(N)+8Θ(N)+Θ(N)=i=0lgn18iΘ(N)=Θ(Nn3)

Tc3:a=8,b=2,f(n)=Θ(n2),logba=3。因此根据第一个条件,Tc1(N,n)=Θ(n3)

4-3

a

代入 n=2m。那么可以写成 T(2m)=2T(2m/2)+Θ(m)

再代入 S(m)=T(2m),那么有 S(m)=2S(m/2)+Θ(m)

b

a=2,b=2,f(n)=Θ(n),logba=1。因此根据第二个条件,得到 k=0,最终 S(m)=Θ(mlgm)

c

由于 S(2m)=Θ(mlgm),回代 n=2m,即 m=lgn,得到 T(n)=Θ(lgnlglgn)

d

可以发现,整个递归树一共只有 Θ(lglgn) 层。

如图所示,最终有 T(n)=lglgnΘ(lgn)=Θ(lgnlglgn)

e

代入 n=2m。那么可以写成 T(2m)=2T(2m/2)+Θ(1)

再代入 S(m)=T(2m),那么有 S(m)=2S(m/2)+Θ(1)

a=2,b=2,f(m)=Θ(1),logba=1。因此根据第一个条件,S(m)=Θ(m)

回代 n=2m,即 m=lgn,得到 T(n)=Θ(lgn)

f

代入 n=3m。那么可以写成 T(3m)=3T(3m/3)+Θ(3m)

再代入 S(m)=T(3m),那么有 S(m)=3S(m/3)+Θ(3m)

S(m)=3S(m/3)+Θ(3m)=9S(m/9)+3Θ(3m1)+Θ(3m)=27S(m/27)+9Θ(3m2)+3Θ(3m1)+Θ(3m)=i=0log3m1Θ(3m)=Θ(lgm3m)

回代 n=3m,即 m=log3n,得到 T(n)=Θ(nlglgn)

4-4

a

考虑使用主定理,那么有 a=5,b=3,f(n)=nlgn,logba=log35>1

因此根据第一个条件,T(n)=Θ(nlog35)

b

由于 a=3,b=3,f(n)=n/lgn=Θ(nlogba/lgn)

那么使用题目 4.6-3 的结论,得到 T(n)=nlglgn

c

考虑使用主定理,那么有 a=8,b=2,f(n)=n7/2,logba=3

因此根据第三个条件,可以构造出 c=22,最终 T(n)=Θ(n7/2)

d

根据 4-3 节的结论,常数附加项不会对递推式的渐进结果产生影响。

因此令 T(n)=2T(n/2)+n/2,那么 T(n)=Θ(T(n))

考虑使用主定理求解 T(n),那么有 a=2,b=2,f(n)=n/2,logba=log22=1

因此根据第二个条件,得到 k=0,最终 T(n)=Θ(nlgn)

也就是说,T(n)=Θ(nlgn)

e

由于 a=2,b=2,f(n)=n/lgn=Θ(nlogba/lgn)

那么使用题目 4.6-3 的结论,得到 T(n)=nlglgn

f

考虑使用 Akra-Bazzi 方法。

由于 i=1kaibi=78,因此 p<1。如果精确解方程 i=1kaibip=1,那么可以得到 p0.879146。并且由于 f(n)=n。那么有

T(n)=Θ(np(1+1nf(x)xp+1dx))=Θ(np(1+1nxpdx))=Θ(np(1+(x1p1p|1n)))=Θ(np(1+(n1p11p)))=Θ(np+nnp1p)=Θ(n)

g

T(n)=T(n1)+1n=T(n2)+1n1+1n=i=1n1i=lnn+O(1)=Θ(lgn)

h

T(n)=T(n1)+lgn=T(n2)+lg(n1)+lgn=i=1nlgi=lgn!=Θ(nlgn)

i

本题目答案参考了此页面的内容,并且更加严谨了一些。

可以发现,T(n) 可以写成如下分段等式:

T(n)={T(0)+k=1n/21lg(2k)if n0(mod2)T(1)+k=1(n1)/21lg(2k+1)if n1(mod2)

接下来证明 T(n)=Ω(nlgn).

n 为偶数时,有 T(n)=T(0)+k=1n/21lg(2k)T(0)+k=1n/21lgn=T(0)+n2lgnn2lgn. 不难发现在这种情况下有 T(n)=Ω(nlgn).

n 为奇数时,有 T(n)=T(1)+k=1(n1)/21lg(2k+1)T(1)+k=1(n1)/21lgn=T(1)+n12lgnn2lgn. 不难发现在这种情况下有 T(n)=Ω(nlgn).

因此综上所述,T(n)=Ω(nlgn).

接下来证明 T(n)=O(nlgn). 以下变换基于 ne2 的假设进行。

n 为偶数时,有

T(n)=k=1n/21lg(2k)=1lg2+k=2n/21lg(2k)1+1n/2dxlg(2x)=1+122ndxlgx=1+122e2dxlgx+12e2ndxlgx

n 为奇数时,有

T(n)=k=1(n1)/21lg(2k+1)=1lg3+k=2(n1)/21lg(2k+1)1lg3+1(n1)/2dxlg(2x+1)=1lg3+123ndxlgx=1lg3+123e2dxlgx+12e2ndxlgx

因此,令 c0=max{1+122e2dxlgx,1lg3+123e2dxlgx}。那么可以写成

T(n)c+12e2ndxlgx=c+ln22e2ndxlnx

ne2 时,不难得到不等式 lnn2(lnn1)。故此有

T(n)c+ln22e2ndxlnxc+ln2e2n(lnx1)dxln2x=c+ln2(xlnx|e2n)=c+nln2lnne2ln22

因此综上所述,T(n)=O(nlgn).

最终有 T(n)=Θ(nlgn).

j

U(n)=T(n)n。将 U(n) 代入到原式,那么得到

U(n)=U(n)+1

V(m)=U(2m)。将 V(m) 带入到上式,那么得到

V(m)=V(m/2)+1

根据主定理的第二个条件,可以得到 V(m)=Θ(lgm)

回代到 U 中,得到 U(n)=Θ(lglgn)

因此有 T(n)=Θ(nlglgn)

4-5

a

将一次项和常数项目全部分离出来,那么等式右边三项可以写成:

z=zzF(z)=i=0Fizi+1=i=1Fi1zi=F0z+i=2Fi1ziz2F(z)=i=0Fizi+2=i=2Fi2zi

三项相加,得到 z+i=2(Fi1+Fi2)zi=z+i=2Fizi

代入 F0=0,F1=1,最终这个式子可以写成 i=0Fizi,也就是 F(z)

b

将 a 的结论整理得到 F(z)zF(z)z2F(z)=z,提取 F(z) 公因式,得到 F(z)(1zz2)=z,最终得到:

F(z)=z1zz2

由于 ϕ=1+52,ϕ^=152,那么得到 ϕϕ^=1,ϕ+ϕ^=1,ϕϕ^=5

由于 (1ϕz)(1ϕz^)=ϕϕ^z2(ϕ+ϕ^)z+1=1zz2,因此 F(z) 还可以写成:F(z)=z(1ϕz)(1ϕ^z)

由于有如下变换:

15(11ϕz11ϕ^z)=15((1ϕ^z)(1ϕz)(1ϕz)(1ϕ^z))=15(ϕϕ^(1ϕz)(1ϕ^z))=1(1ϕz)(1ϕ^z)

因此 F(z) 还可以写成:F(z)=15(11ϕz11ϕ^z).

c

F(z)=15(11ϕz11ϕ^z)=15(i=0ϕizii=0ϕ^izi)=15i=0(ϕiϕ^i)zi

d

由题目 c 得到的等式,代入题目求和项中的 Fi,有 Fi=ϕiϕ^i5=ϕi5ϕ^i5

可以发现,对于 i0,|ϕ^i5|<0.5 均成立。因此,Fi=ϕ^i5 最接近的整数即为 Fi

e

考虑式子 Fi+2ϕi 的值。那么有

Fi+2ϕi=15(ϕi+2ϕ^i+2)ϕi=35510ϕi35510ϕ^i=35510(ϕiϕ^i)

由于 ϕ>ϕ^,因此 Fi+2ϕi0,即有 Fi+2ϕi

4-6

a

假设好的芯片一共有 k 个,其中满足 knk

那么从这 nk 个坏芯片中选择出 k 个坏芯片。这 k 个坏芯片的策略是:如果另一个芯片是好芯片,那么显示为坏结果如果另一个芯片是坏芯片,那么显示为好结果。

按照这种策略,只要从这 2k 个芯片中取出任意 2 个芯片检测,那么教授旧无法区分哪 k 个芯片是好的,哪 k 个芯片是坏的,因为两个芯片互相检测结果总是一致的,

b

现在题目的假设是:好芯片严格多于坏芯片。

整个策略如下:首先,如果当前芯片个数 n 是奇数,那么均匀随机选择一个芯片留下,对剩下的 n1 个芯片进行递归操作,等操作完成再回头考虑这个被留下的芯片;否则什么都不用做。在一轮中,每次随机取出 2 个芯片进行测试。如果 2 个芯片的测试结果是 “2 个都是好芯片”,那么丢弃其中 1 个芯片,另 1 个芯片留到下一轮测试;否则 2 个芯片都丢弃。这个过程由算法 GET-GOOD 描述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 子程序`TEST(c1, c2)`表示对芯片c1, c2进行测试的结果。用True表示全好的报告,用False表示存在1个芯片是坏的报告。
GET-GOOD(chips)
if chips.size == 0
return NIL
else if chips.size == 1
return chip[0]
else if chips.size % 2 == 0
let C be new array
for i = 0 to chips.size - 1 by 2
if TEST(chips[i], chips[i + 1]) == True
INSERT(C, chips[i])
return GET-GOOD(C)
else
// chips[0]是保留的那个芯片。
let C be new array
for i = 1 to chips.size - 1 by 2
if TEST(chips[i], chips[i + 1]) == True
INSERT(C, chips[i])
now = GET-GOOD(C)
if now == NIL
return chips[0]
else
return now

因此在一轮测试中,需要进行 n2 次测试。在一轮测试完成后,最多剩下 n2 个芯片。

接下来说明:经过一轮的测试后,剩下的芯片仍然满足:好芯片仍然严格多于坏芯片。

可以知道,如果算法 GET-GOOD 传入的芯片中,好坏的个数相同,那么最终这个算法的递归终点将是第 2 行的 NIL。因为在第 7 行的 for 循环完成后,得到的 C 数组中,好芯片和坏芯片的个数仍然相同。最终随着递归的进行,每一对好坏芯片都将被抵消,最终找不到任何一个好芯片。

如果算法 GET-GOOD 传入的芯片中,好芯片要比坏芯片多,那么在这一轮测试中,假设芯片的个数为 n,那么考虑如下 2 个情况:

如果 n 是偶数,在这 n2 次测试中,有 a 次是拿出了 2 个好芯片进行测试,有 b 次是拿出了 1 个好芯片,1 个坏芯片进行测试,有 c 次是拿出了 2 个坏芯片进行测试,需要注意的是,在测试的过程中,a,b,c 的值是无法被统计。那么可以知道好芯片的个数为 2a+b,坏芯片的个数为 2c+b。按照假设,有 2a+b>2c+b,即得出 a>c。在 b 次不同好坏芯片的测试中,所有芯片都丢弃;a 次全好芯片测试中,将会恰好保留 a 个好芯片;在 c 次全坏芯片测试中,将会至多保留 c 个坏芯片(因为两个坏芯片同样会有可能报告对方是坏的)。由于 a>c,因此这一轮测试完成后,保留的好芯片必然严格多于坏芯片。最终递归终止时,所有坏芯片将会被丢弃,通过第 4 行的代码找到一个好芯片。

如果 n 是奇数,那么有如下 2 种情况进行讨论,注意需要随机留出一个芯片,假设为 chips[0]

1

如果算法 GET-GOOD 传入的芯片中,好芯片要比坏芯片多出 3 个或以上,那么无论留下来的是好芯片还是坏芯片,按照偶数时的情况,第 16 行代码中,变量 now 必定是一个好芯片,直接返回。

2

如果算法 GET-GOOD 传入的芯片中,好芯片要比坏芯片多出恰好 1 个,那么有如下 2 情况讨论。

如果留下来的是好芯片,那么剩下的 n1 个芯片中,好坏的个数相同。上面 13 行的 for 循环完成后,数组 C 的好坏芯片个数相同。按照上面的结论,第 16 行代码对数组 C 进行递归调用后,得到的必定是 NIL。那么返回留下的好芯片 chips[0] 即可。

如果留下来的是坏芯片,那么剩下的 n1 个芯片中,好芯片多于坏芯片。按照偶数时的结论,第 16 行代码中,变量 now 必定是一个好芯片,直接返回。

故在好芯片严格多于坏芯片的情况下,算法 GET-GOOD 总能找到一个好芯片。

c

根据题目 4-6-b 的结论,假设 n 个芯片的比较次数为 T(n),那么可以给出下列不等式:

T(n)T(n2)+n2

根据主定理的第二个条件,不难得到 T(n)=O(n)

d

由于找出一个好的芯片需要 O(n) 次比较,那么使用这个好的芯片对其它芯片进行测试就能够找到所有好芯片,总共需要 n1 次比较。

因此,最终找到所有好芯片的次数为 O(n)+n1=Θ(n) 次。

4-7

a

充分性:

k=i+1,k=j+1,那么得到等式 A[i,j]+A[i+1,j+1]A[i,j+1]+A[i+1,j]。充分性成立。

必要性:

A[i,j]+A[i+1,j+1]A[i,j+1]+A[i+1,j] 通过移项,得到:

A[i,j]A[i,j+1]A[i+1,j]A[i+1,j+1]

令函数 fj(x)=A[x,j]A[x,j+1],那么对于 1x<m,由上面的等式,发现 fj(i) 是一个递增函数。因此,1i<km,都有 fj(i)fj(k) 成立。即有 A[i,j]+A[k,j+1]A[i,j+1]+A[k,j] 都成立。

同理,可以得出 1j<ln,都有 A[i,j]+A[i+1,l]A[i,l]+A[i+1,j]

最终根据传递性,总有 A[i,j]+A[k,l]A[i,l]+A[l,j] 成立,因此必要性成立。

b

37232932216710533430313213964321156

c

本题使用反正法进行证明。

假设存在 a,b 满足 1a<bm,有 f(a)>f(b)

根据 f 函数的定义:f(i) 是第 i 行中最左的最小元素的列下标,可以得到:A[a,f(b)]>A[a,f(a)],注意此式子不能取等号;还可以得到 A[b,f(b)]A[b,f(a)].

根据这两条不等式可以得到 A[b,f(a)]+A[a,f(b)]>A[a,f(a)]+A[b,f(b)],与 Monge 矩阵的定义矛盾。

因此 1a<bm,都有 f(a)f(b)

d

由于目前已经知道 f(2),f(4),f(6),,f(2k) 的值,并且由于已知 f(0)f(1)f(2)f(3)f(m)。为了计算 f(1),f(3),f(5),,f(2k+1) 的值,假设 f(0)=1,有:

S(n,m)=i=1m/2(f(2i)f(2i2)+1)=f(m)f(0)+m/2=O(n+m)

e

为了解决整个求解问题,可以写出 S(m)=S(m/2)+T(n,m)

由于 T(n,m)=O(n+m),那么可以假设 T(n,m)an+bm

S(m)S(m/2)+an+bmS(m/4)+an+bm+an+bm/2S(m/8)+an+bm+an+bm/2+an+bm/4=i=0lgman+bm2i=bm+anlgm

因此 S(m)=O(m+nlgm)