算法导论5.3 随机算法


在雇佣问题中,如果应聘者是以随机顺序出现的话,雇佣一个新的办公室助理的期望次数是lnn。这个算法是随着输入的变化而变化的。对于某个特定的输入,它总是会
产生固定的雇佣次数。

如果先对应聘者进行随机排列,此时随机发生在算法上而不是发生在输入分布上。 每次运行这个算法,执行依赖于随机的选择,而不是依赖于输入。这就是随机算法和概率分析的区别。

RANDOMIZED-HIRE-ASSISTANT(n)
1 randomly permute the list of candidates
2 best  0      ® candidate 0 is a least-qualified dummy candidate
3 for i  1 to n
4       do interview candidate i
5          if candidate i is better than candidate best
6             then best  i
7                  hire candidate i

随机算法事实上就是在算法里,对输入预先进行重排,其他完全一样。


在这里,要介绍2种对输入进行重排的算法,他们是随机重排。这两个方法都能产生均匀的随机排列。(每一种排列都等可能的被产生)。

要特别注意均匀随机排列的定义!!!!本书下面给出的2个算法对数组进行重排,产生的都是均匀随机排列,并给出了严格的数学证明,理论性很高,我们在这里这着重于介绍和了解这两种方法,不深究证明,欲看证明的可去看书。


---------------------------------------------------------------------------------------------------------------------------------------------------


随机排列数组:


1)PERMUTE-BY-SORTING(A)

为数组的每个元素赋一个随机的优先级,然后根据优先级对数组A进行排序。

PERMUTE-BY-SORTING(A)
1 n  length[A]
2 for i  1 to n
3      do P[i] = RANDOM(1, n

3

)
4 sort A, using P as sort keys
5 return A


这样显然可以打乱数组的顺序,关键在于我们要去证明它是均匀随机打乱的。这个要根据均匀随机排列的定义,即证明产生每一个排列的概率都是1/n!

潜在的,我们可以知道:


a)如果一个算法总共还产生不到n!种排列,那么显然它不是一个均匀随机排列的算法。课后某习题

b)有人可能会说,要证明一个排列是均匀随机排列,只要证明每个元素在每个位置上出现的概率是1/n就可。这是对均匀随机排列的误解。课后某习题

PERMUTE-BY-SORTING比较难,不能直接看出可以产生多少种排列。



2)RANDOMIZE-IN-PLACE(A)

对数组一遍循环,每个元素A[i]与  A[i]到最后一个元素  中的某个交换(如下代码),容易看出,总共的排列数就是n!个

RANDOMIZE-IN-PLACE(A)
1 n  length[A]
2 for i  to n
3      do swap A[i]  A[RANDOM(i, n)]


对于1)2)是均匀随机排列的证明这里就不讲了,书上有。


--------------------------------------------------------------------------------------------------------------------------------------------------


习题 


(证明均匀随机排列的过程是非常麻烦的,我们重点关注上面画底线的a,b两条,来判断某个算法是否可以产生均匀随机排列就行)




5.3.2   Kelp教授决定用下列算法来随机产生非同一排列的任意排列,他实现了意图吗?

PERMUTE-WITHOUT-IDENTITY(A)
1 n  length[A]
2 for i  1 to n
3      do swap A[i]  A[RANDOM(i + 1, n)]


不行,这段代码总共只能产生(n-1)!种排列(自己算),达到他的意图的必要条件就需要能够产生n!-1种排列。

上述第a)点。



5.3.3  假设不是将 A[i] 与 A[i....n] 上的数随机的交换一个(注意这是我们的正确算法),而是每次将它与数组上任意位置上的数随机交换,可以产生均匀随机排列吗?

PERMUTE-WITH-ALL(A)
1 n  length[A]
2 for i  1 to n
3      do swap A[i]  A[RANDOM(1, n)]


不能,也是第a)点,可以自己分析下。

举个特例,假设排列长度为n=3。那么就要调用3次RANDOM,每次返回3个值中的一个,则执行完过程PERMUTE-WITH-ALL后将会有27种可能的结 果。因为排列长度为n,则一共有3!=6个排列,如果PERMUTE-WITH-ALL产生均匀的随机排列,那么每个排列出现的概率均为1/6。也就是说 每个排列都应该出现m次使m/27=1/6。由于不存在整数m使m/27=1/6,因此PERMUTE-WITH-ALL不一定产生均匀的随机排列。


5.3.4  Armstrong建议用下列过程来产生均匀随机排列:

PERMUTE-BY-CYCLIC(A)
1  n  length[A]
2  offset  RANDOM(1, n)
3  for i  1 to n
4       do dest  i + offset
5          if dest > n
6             then dest  dest -n
7          B[dest]  A[i]
8  return B

证明任意元素在B中任意位置出现的概率都是1/n,证明该算法不能产生均匀随机排列。

1)注意第2行,offset在这就求出来了,在for中使用的时候是一个定值。

offset可以有n个值,所以任意元素在B中任意位置出现概率都是1/n.

2)这段代码只能产生n个不同的排列(原因仍是第2行)


这就说明了划线部分b)




------------------------------------------------------------------------------------------------------------------------------------------------


总结:

1)均匀随机排列的定义

2)两个均匀随机排列

3)均匀随机排列证明比较难,但要会怎么去判断一个算法能否产生均匀随机排列



posted @ 2011-08-11 16:16  jinmengzhe  阅读(2148)  评论(0编辑  收藏  举报