均匀随机排列数组

1. 简述

    本文主要是关于均匀随机排列数组的一个学习总结,主要参考资料是算法导论。

2. 相关题目

    据说腾讯一个题目:对于一个斗地主游戏,给出一个发牌的算法,让每个人的牌确保随机。
    分析:考虑假设有N张牌,要分出来M张牌,给K个人。我能想到的是,N张牌有N种排列,随机产生一种排列,将产生排列的前M张牌依次分给K个人。使用均匀随机排列算法,能够保证:对于N张牌的N!种排列,且得到的任意一种排列的概率都是相同的,即都为1/(N!)。

3. 判定方法

    对于一个算法能否保证均匀随机排列数组,主要考查两点:
  · 产生的排列个数是N!个
    · 每种排列的概率相同,即都为1/N!

4. 两个算法

 ·方法一:首先,得到一个优先级数组P,然后根据优先级数组P来排序原数组A。关键在于优先级数组P,要保证能够得到n!种排列,且每种排列的概率相等。   

PERMUTE - BY - SORTING(A)
  n 
<-  length[A]
  
for  i  <-   1  to n  //  产生优先级
     do  P[i]  =  RANDOM( 1 , n * n * n)
  sort A, 
using  P  as  sort keys  //  根据优先级排序
   return  A

    RANDOM中使用n的立方是为了使得产生的优先级尽量是唯一的,因此对这个方法的证明的前提是分配的优先级是唯一的。
    考虑优先级数组正好是升序的这一个特殊序列,概率为(1/n) * (1/(n-1)) * ... * (1/1) = 1 / (n!)
    对于优先级数组的其他情况,也能得到类似结果(具体看算法导论)。
    因此一共能得到n!个序列,每个序列的概率都是相同的,满足判定方法。
 ·方法二:第一次交换A1与Rand(1,n),第二次交换A2与Rand(2,n),...,第n次交换An与Rand(n,n)   

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

    概率分析忽略了,说实话证明较为复杂,先不看了,下次再说了。
    方法一的时间复杂度为O(N+N*LogN),方法二的时间复杂度为O(N)。

5. 一个反例   

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

    感觉上对于升序的概率是:1/(n-1) * 1/(n-2) * ... * 1 = 1 / (n-1)!每个排序的概率都一样,那么也就是只有(n-1)!种排列。其实对于A[i]交换的元素下标是在[i+1, n]这个范围内,即每个元素肯定是与后面的元素交换,不会与自己交换,所以对于A1肯定越交换越往后,无论多少次随机都不会被换到原来的位置了,因此不能保证n!中排列,不是均匀随机排列。 
6. 参考
    算法导论,第二版,5.3节,随机算法,Page58

    腾讯大厦面试经历    http://www.iweber.org/weber/?tag=%e8%85%be%e8%ae%af

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值