随机取样问题

随机取样问题


输入包括两个整数m和n其中m>n,输出是0-m-1范围内的n个随机整数的有序列表,不允许重复。希望得到没有重复的有序选择,其中每个选择出现的概率相等

#include<iostream>
using namespace std;
int main()
{
    int n = 10;
    int m = 100;
    int selected = n;
    int remaining = m;
    srand(time(0));
    for(int i=0;i<m;i++)
    {
        if(rand()%(m-i) < n)
        {
            cout<<i<<" "<<m<<" "<<endl;
            n--;
        }
    }
    return 0;
}

 

 

当目标改为随机抽取n个有序整数

该算法时间和m成正比,当m很大而n很小时不合适

将算法啊改成在初始为空的集合里面插入随机整数,直到个数足够

#include<iostream>
#include<set>
using namespace std;
int main()
{
    int n = 10;
    int m = 100;
    int selected = n;
    int remaining = m;
    srand(time(0));
    set<int> s;
    while(s.size()<n)
    {
        s.insert(rand()%m);
    }
    set<int>::iterator ite;
    for(ite=s.begin();ite!=s.end();ite++)
    {
        cout<<*ite<<endl;
    }
    return 0;
}

 

利用set的特性,每个元素在set中只出现一次,因此在插入时无需判断是否已经插入过。
并且自动排序,输出时已经是有序的

 

但是插入操作每次都需要对红黑树进行调整,时间主要消耗在建立集合中

 


另一种方法:
将包含n个数的数组顺序打乱,然后把前m个元素排序输出
实际上只需要打乱前m个元素即可

void genshuf(int m, int n)
{
    int i, j;
    int *x = new int[m];
    for(i=0;i<m;i++)
        x[i]=i;
    for(i=0;i<n;i++)
    {
        j = randint(i, n-1);
        swap(x[i], x[j]);
    sort(x, x+n);
}


参考:编程珠玑

posted @ 2012-08-16 15:52  w0w0  阅读(222)  评论(0编辑  收藏  举报