Alex He

...永远保持希望与激情...约会未来更强大的自己...

 

随机选取指定比例元素初探

随机选取指定比例元素初探

我们常常需要从集合中随机选择若干比例的元素处理。如从某班集中选择1/3的同学来打扫卫生;从某个文档集中选择7/10的文档进行处理(这是我遇到的问题,哈哈...)等等...

如何一般性的解决这个问题呢?

首先进行问题描述:设集合A包含n个元素,现需得到A的子集B,使得B集合中元素个数m满足指定要求,(m/n=0.7),即要从A中选择出m/n的元素. 另外元素的选择要满足随机性.

初一看这问题似乎很简单, 也的确简单, 这里我只是想给出另一种思路,并希望探讨该方法的可行性和其是否的确具有优势!

方案一:由于需要满足随机性,那么不可避免地需要使用随机数。需要从n个数(不妨设为数)中选择随机选择m个数,是否可以每次都从n个数中随机选择一个数“丢进”集合B中,直到B中元素个数为m 

for(int i=0;i<m;i++)
{
        index
=random.nextInt(n);//返回0到n-1的随机数
         B.add(A.get(index));
}

 虽然上面的时间耗费很小:O(m)(不考虑从集合中取元素和存元素那些复杂的分析步骤),但是很明显上面的方法有问题,因为这里的伪随机数可能选择重复了,也即这里是有放回的样本抽取问题。可分析选择出不含重复元素的集合B概率为.可见随着m的增大,其概率是很小的.

为了满足不重复性,是否可以用:

while(B.size()<m)
{
    index
=random.nextInt(n);
    
if(!B.exist(index))
        B.add(A.get(index));
}

 这样应该就可以避免元素的重复了,但是也应该看到这里的时间耗费要高很多,对于每个希望被选入的元素都要判断其是否存在于集合中。这里的耗费其实是很大的,特别是对于m/n越接近1,随机选择重复元素的可能性就会越大。这里的时间复杂度应该大致为O(m*n)(估计的,呵呵,应该没人会仔细看这篇文章更不会有人去仔细分析这个了)。 

HashSet hs;//定义hashset
while(B.size()<m)
{
    index
=random.nextInt(n);
    
if(!hs.contains(index))
    {
        hs.add(index);
        B.add(A.get(index));
    }
}

 这样用空间换时间其实实质没变。所以我认为它们还属于同一类方法。
方案二:同样,需要产生随机数来选择元素。不过这里我们用到使用频数来估计概率的方法来解决。对于每个元素,产生一个0-1的随机数,如果这个数小于m/n(如0.7),那么我们则选择该元素;如果其大于等于m/n我们则不选。因为0-1的随机数是由一个均匀分布产生的,则我们有理由相信,对于大量的抽样,能够抽取到m/n个元素。也可以这样理解:对于每个元素,其有0.7的可能性属于A,有0.3的可能性属于A’(U-A);那么通过无数次的选择这样的数,则我们有理由相信,其中有7/10的跑到了A’这边,而3/10跑到了A这边。

for(int index=0;index<n;index++)
{
    
float ram=random.nextFloat();//产生从0-1.0间的随机数
    if(ram<(float)m/n)
        B.add(A.get(index));
}

 

 很明显这里的时间耗费仅仅为O(n),可能比O(m)要大些,不过该方法能保证得到没有重复的元素集合。

这里的问题就是:

(1):该方法在大量抽样的情况下满足(甚至是无穷情况),而对于实际应用中是否可以使用该方法来模拟?

(2):由于random也是一个伪随机数,所以这种利用伪随机数到底是否可靠(可靠性到底有多少)不好意思思,第一个博文,质量不高,还请见谅。。。

posted on 2010-09-26 13:29  Alex木头  阅读(518)  评论(2编辑  收藏  举报

导航