取样问题

随机输入两个整数m和n,其中m < n,输出是0到n-1范围内的m个随机整数的有序列表,不允许重复。
方案一:使用随机数的想法,通过取模的方式来控制产生的随机数的范围,然后通过设置一个计数器的方式控制选取的随机数的个数。

void getrand(int m,int n)
{
    for(int i = 0;i < n;i++)
    {
        if(bigrand()%(n-i)<m)
            cout<<i;
            m--;
    }
}
int bigrand()
{
    return RAND_MAX*rand()+rand();
}

方案二:使用C++标准模板库,使用set容器,利用set容器的自带排序的功能,但是使用set容器也有缺点,缺点就是空间开销较大。

void getsets(int m,int n)
{
    set<int> S;
    while(S.size()<m)
        S.insert(bigrand()%n);
    set<int>::iterator i;//迭代器
    for(i = S.begin();i!=S.end();i++)
        cout<<*i<<endl;
}

方案三:最初的想法是把n个元素的数组打乱之后输出,再仔细思考可以发现,将数组的前m个元素打乱顺序进行输出即可。

void getrands(int m,int n)
{
    int i,j;
    int *x = new int[n];
    for(i = 0;i < n;i++)
        x[i] = i;
    for(i = 0;i < m;i++)
    {
        j = randint(i,n-1);
        int temp = x[i];
        x[i] = x[j];
        x[j] = temp;
    }
    sort(x,x+m);
    for(i = 0;i < m;i++)
        cout<<x[i];
}
int randint(int u,int l)
{
    return u + bigrand()%(l-u+1);
}

方案四:以上的方案在一种极端情况的时候会出现浪费很多随机数的情况,当m和n的取值十分接近的时候,取模操作找到满足要求的余数的概率机会变得很小,借助佛洛依德算法就可以很好解决这个问题。

void floydrand(int m,int n)
{
    set<int> S;
    set<int>::iterator i;
    for(int j = n-m;j<n;j++)
    {
        int t = bigrand(j+1);
        if(S.find(t)=S.end())
            S.insert(t); // t is not in S
        else
            S.insert(j)
    }
    for(i = S.begin();i != S.end();i++)
        cout << *i << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值