Introduction_to_Algorithms_chap5

来源:互联网 发布:英译汉软件下载 编辑:程序博客网 时间:2024/04/30 17:48

第五章 概率分析和随机算法

课后练习

5.1-1

如果我们能够比较任意两个应聘者的优劣,那么我们就能够对所有的应聘者按照优劣进行排序,之后按顺序对每个人赋予rank值,这样我们就知道了原来应聘者rank值的序列。


5.1-2

要利用Random(0, 1)实现Random(a, b),我们可以把问题转化为实现a+Random(0, b-a)。之后可以利用Random(0, 1)来生成二进制下随机数的每一位。由于数的范围是[0,b−a][0,b−a],所以位数的范围是[1,1+⌊lg(b−a)⌋][1,1+⌊lg⁡(b−a)⌋]。如果生成的数大于b-a,就将其舍去重新生成,直到产生符合要求的数为止。

Random(a, b)1  n = 1, s = 22  while s <= b - a3       n = n + 14       s = s * 25  r = b - a + 16  while r > b - a7      for i = 1 to n8          r.bit[i] = Random01()9  return r + a

假设要生成的数最多为n,如果第一次生成的数成功那么每个数的概率为(1/2)^n;
如果第一次生成的数失败且失败的概率为p,那么第二次生成数成功时每个数的概率为p^i*(1/2)^n,所以最终每个数生成的概率为

i=0pi(12)n

即所得每个数的概率是相同的。
每一次生成需要的时间为 k = ⌊lg(b−a)⌋+1 ,第i次生成成功的概率为1−p,那么时间期望是

E(T)=i=1ikPT=ik

=i=1ikpi1(1p)

=k(1p)i=1ipi1

=k1p

=lg(ba)+11p

1p=ba+12lg(ba)+1>ba+12(ba+1)=12

E(T)<2(lg(ba)+1)=O(lg(ba))


5.1-3

如果执行两次Biased-Random,出现两个1的概率为p^2,出现两个0的概率为(1−p)^2,出现一个1和一个0的概率是2p(1−p)。 在0、1各一个的情况下,由于先出现1和后出现1的概率是相同的,所以可以利用这一点来设计等概率出现0、1的情况。

Random01()1  while true2      x = Biased-Random()3      y = Biased-Random()4      if x != y5           return x

E(T)=i=12p(1p)(12p(1p))i1)=12p(1p)=O(12p(1p))


5.2-1

当第一个应聘者就是最佳人选的时候只需要聘用一次,这时的概率为1/n。
当所有的应聘者按照从劣到优的顺序排列时需要聘用n次,此时的概率为1/(n!)。


5.2-2

由于第一个应聘者肯定会被聘用,所以第一个应聘者肯定不是最优的,设倒数第i好的应聘者的rank值为i,ri为第i个应聘者的rank值,那么1≤r1< n1, 记第一个应聘者的rank值为i的事件为AiAi,出现两次聘用的事件为B,那么

P(Ai)=1n

最优的应聘者应该在比第一个应聘者rank值大的应聘者序列中第一个出现,概率为

P(B|Ai)=1ni

所以总概率为

P(B)=i=0n1P(Ai)P(B|Ai)

=i=0n11n1ni

=1ni=1n11i

=1n[ln(n1)+C]


5.2-3

由于出现每个面的几率相同,为1/n,所以期望

E=i=1ni1n=n+12


5.2-4

由于每个人拿到自己的帽子的概率是相同的,为1/n,设Ai=1为第i个人拿到了自己的帽子,那么

PAi=1=1n

E(Ai)=11n+0n1n=1n

E(A)=E(i=1nAi)

=i=1nE(Ai)

=i=1n1n

=1


5.2-5

设Aij=1为A[i], A[j]互为逆序对。由于序列是随机的,所以一个元素比另一个大的概率是1/2,即

这道题也可以说明插入排序时平均的移动次数为最差时的一半。


5.3-1

只要把第一次循环结果作为初始条件即可

Randomize-In-Place(A)1   n = A.length2  swap A[1]  A[Random(1, n)]3  for i = 2 to n4      swap A[i]  A[Random(i, n)]

然后初始条件变为序列A[1, 1]以1/n = (n−1)!/(n!)的概率出现A的一种1-permutation,其他和原算法保持不变。


5.3-2

这个算法能够产生不同的全排列,但是不能够等可能的产生所有的全排列。例如,当A的长度为3的时候,与原先不同的全排列有n!-1 = 5种,但是该算法第一遍循环的时候放在A[1]的数有两种可能A[2]、A[3],第二边循环的时候放在A[2]的数只有一种可能A[3],所以一共能产生的全排列数为2,小于总的全排列数,故方法错误。


5.3-3

这个算法产生的每个全排列的可能性是不同的。例如,当A的长度为3的时候,该算法产生的结果一共有33=27种可能33=27种可能,但是长度为3的全排列最多有3!=6种,所以这些结果里肯定有相同的全排列。由于产生的结果需要均匀分布(uniform distribution),所以出现的每种全排列的次数应该相同,但是由于27不能被6整除,所以每种全排列出现的可能是不同的,故算法错误。


5.3-4

由于产生的随机数范围是[1,n],而全部的位置有n个,所以得到的位置不会重复并且所有位置都可能取到,故在每个位置上的概率相同为1/n。但是该算法是错误的,因为每次放到B中的位置是随机的,所以不能保证B中的每个位置都有赋值,故不能保证B是A的全排列。


5.3-5

取得全部不同的序列的种数为

Ann3=n3!(n3n)!

所有的种数为(n^3)^n,所以全部不同的概率

P(U)=Ann3(n3)n=n3!(n3n)!(n3)n(n3nn3)n=(11n2)n11n


5.3-6

如果产生了优先级相同的情况,那么重复生成一组优先级,直至出现全部不同的情况。

Not-Unique(A)1 n = A.length2 sort A to a new array B[1..n]3 for i = 1 to n - 14     if B[i] == B[i + 1]5         return true6 return falseRandomize-By-Sorting2(A)1 n = A.length2 let P[1..n] be a new array3 do4     for i = 1 to n5         P[i] = Random(1, n*n*n)6 while Not-Unique(P)7 sort A, using P as sort keys

假设一次生成出现重复的概率为r,那么每种全排列出现的概率为

i=i(1r)ri11n!=1n!

假设每次生成优先级并判断重复的时间为k=O(nlg⁡n),那么总时间的期望为:

E(T)=i=1kiPT=ik

=i=1ki(1r)ri1=k1r

由5.3-5可知

1r11n

所以

E(T)=k1rk11/n=nn1k2k=O(nlgn)

故算法的期望时间复杂度不变。


5.3-7

Initialization: 首先当m=0,n=n0时,我们有∅以概率1/C(0,n0) =1的概率成为(1,⋯,n0)的一个子集。

Maintenance: 接下来,每次迭代开始前我们假定有每种(1,⋯,n)的m-子集S都以为概率1/C(m,n)出现。新的子集可以看作原来的子集新添一个元素。令新子集包含数n+1的事件为B,出现一种包括数n+1的新子集的事件为Xi,取出的随机数i∈S的事件为C。如果C发生,那么B肯定发生:

P(C)=mn+1P(C¯¯¯)=1mn+1P(BC)=P(B|C)P(C)=1mn+1=mn+1

如果C不发生,那么数n+1有可能从剩下的n-m+1个数中选出,概率为:

P(BC¯¯¯)=P(B|C¯¯¯)P(C¯¯¯)=1nm+1(1mn+1)=1n+1

这样就可知B的概率:

P(B)=P(BC)+P(BC¯¯¯)=m+1n+1

由于新的集合包含了之前的子集S,所以:

可知当新的集合包含数n+1时,每种可能都以相同概率出现。如果取出的随机数i∉S,增加的一个数能从剩下的n-m个数中取出,令出现不包括数n+1的新子集的事件为Yi这时:

P(Yi|B¯¯¯)=1Cmn1nm

于是可以算出每种子集出现的概率:

由于当新子集包含和不包含数n+1时每种情况出现的概率都相同为1/C(m+1,n+1),当m和n增1之后满足了下一次迭代的前提。

Termination: 最后当迭代结束时,得到的m-子集的每种可能都以1/(Cm,n)的概率出现。


5.4-1

要考虑有人和你生日相同,我们可以考虑没有人和你生日相同的情况,一个人和你生日相同的概率为1/365,所以不同的概率为1-1/365,n个人都和你生日不同的概率为(364/365)^n,所以我们只要保证:

(364365)n12 n1lg(364/365)253

要有至少两个人生日是7.8,那么就要排除掉没有人生日是7.8和只有一个人是7.8的情况,概率为:

(364365)n+(364365)n1=(364365)n1(1+1365)=366365(364365)n112 n11+lg(366/365)lg(364/365)255


5.4-2

显然当投掷次数小于2时不可能有箱子装有两个球,当投掷次数大于b时肯定有箱子装有两个以上的球。 所以我们只要考虑2≤k< b的情况。令第i次投掷后任意箱子球数小于2的事件为Bi,第i次投掷到空箱子的事件为Ai,那么:

那么第k次投中已有球的箱子的概率:

所以投掷次数的期望:

E=k=2bkPk


5.4-3

只需要两两互斥即可,因为只用到了性质

Pbi=r,bj=r=Pbi=rPbj=r


5.4-4

利用随机变量指示器(indicator random variables)来求解,令:

Xijk=Ii,j,k

设第i个人的生日为Bi,一年有m天,则有:

Pbi=r,bj=r,bk=r=Pbi=rPbj=rPbk=r=1m3

可以求得期望

令X为三人生日相同的组数,总人数为n,可知:

当m(m−1)(m−2)≥6*n^2时,有三个人生日相同的期望大于1,此时可以求得:

m=Θ(n23)


5.4-5

这是生日悖论(birthday paradox)的反问题,一个k-string相当于一个每个人的生日组成的序列,n相当于一年的天数,产生一个k-permutation即为每个人的生日都不相同。所以概率为:

AKnnk


5.4-6

首先求空盒子数量的期望,令Xi=I{盒子i是空的},那么

E[Xi]=PXi=1=(n1n)n

令X为空盒子的数量,那么

由于

limn(11n)n=1e

所以在n较大时空盒子数量的期望接近n/e。接下来考虑只有一个球的情况,令Xi=I{盒子i中有一个球},那么

E[Xi]=PXi=1=n(n1n)n11n=(n1n)n1

令X为空盒子的数量,那么

由于

n(11n)n1=n(11n)n11n

所以在n较大时空盒子数量的期望接近n^2/e(n−1)。


5.4-7

令Aij表示从第i次开始至少有j个连续的H面出现,那么有

PAi,lgn2lglgn=12lgn2lglgn=(lgn)2n

所以每个长度为lgn−2lglgn的组都没有出现连续H面次数超过lgn−2lglgn的概率为


思考题

5-1

a) 令Xi代表第i次Increment操作后计数器增加的数,那么

令Yn表示n次Increment操作后计数器增加的数,可知期望为

b) 求方差(variance)可以用到公式

所以

求和可得D(Yn)=99n


5-2

a) 我的想法是利用一个长度为n的数组来标记某个元素是否被查看过,并且记录已经查看元素的数量,伪码如下:

Random-Search(A, key)1  n = A.length2  c = 03  let B[1..n] be a new array4  for i = 1 to n5      B[i] = 06  while c < n7      j = Random(1, n)8      if A[j] == key9          return j10    if B[j] == 011       B[j] = 112        c = c + 113return NIL

b) 令A为检查元素的次数,那么

PA=k=1n(n1n)k1

利用几何分布公式可以算出期望为

E[A]=k=1kPA=k=n

c) 令A为检查元素的次数,那么

PA=i=kn(nkn)i1

E[A]=i=1iPA=i=nk

d) 令Xi表示i-1个元素被检查过后检查到一个新元素的次数,令Xij表示第i-1个元素被检查过后的j次检查发现了新元素,那么

当算法终止时的检查次数为X=X1+X2+⋯+Xn

e) 由于要找元素出现在每个位置的概率相同为1/n,所以期望为

E=k=1nk1n=n+12

f) 如果有k个数符合要求,那么每个位置出现要找元素的概率为k/n,设X为要找的元素第一次出现的位置,那么概率为

PX=i=kn(nkn)i1

于是可得期望

E[X]=i=1nkikn(nkn)i1<nk=O(nk)

g) 如果没有要找的元素,那么将所有元素遍历一遍之后介素,所以运行时间是n。

h) 可以将第二种方法(Deterministic Search)看作是第三种方法(Scramble Search)的一种特殊情况,其他的情况都是与这种特殊情况对等的,所以同理可得期望运行时间是O(n/k),最差情况为n。

i) 第二种方式较好,时间复杂度和第三种一致,但是省去了产生全排列的过程。

0 0
原创粉丝点击