简单但比较高效的解决:随机获取N个数字,这些数字在指定的范围内,获取的数字不能重复

在做游戏的时候遇到这个问题:随机指定范围的数字,但不能重复。

一开始的想法是:用一个双循环,直接用【rand()%范围数字】的方法得到一个数字,然后和数据结构里面的已有元素进行比对,如果重复就不添加,退出内层循环,然后一直不断判断直到添加到数据结构里的数量符合要求。代码如下:

void getRandomNum(int range, int count)
{
    vector<int> vec;
    for (int i=0; i<10; i++)
    {
        vec.push_back(i);
    }
    
    srand(time(NULL));
    while (1)
    {
        int idx = rand() % 60;
        vector<int>::iterator itr = vec.begin();
        for (; itr != vec.end(); ++itr)
        {
            if (*itr == idx)
                break;
        }
        if (itr == vec.end())
        {
            vec.push_back(idx);
            if (vec.size() == count)
                break;
        }
    }
}


这种算法效率很低!


这里引入一种效率比这个高很多的办法,简单说一下思路:先用一个数组A保存范围内的每一个数字(当做索引用),然后写个洗牌算法把这个数组的元素随机打乱,最后用另外一个数组B存储数组A的前N个元素的值。这里数组B就是要得到的结果。下面是实现代码:

// 洗牌算法
void shuffle(vector<int>* vec)
{
    int size = vec->size();
    srand((unsigned)time(nullptr));
    for (int i=0; i<size; i++)
    {
        int temp = (*vec)[i];
        int r = rand()%size;
        (*vec)[i] = (*vec)[r];
        (*vec)[r] = temp;
    }
}

void getRandomCount(int range, int count)
{
    vector<int> m_aviable; // 存储结果的数组
    vector<int> v_range; // 保存范围的索引值
    for (int i=1; i<=range; i++)
    {
        v_range.push_back(i);
    }
    
    // 洗牌
    shuffle(&v_range);
    
    // 取洗牌后数组里前count个数。
    for (int i=0; i<count; i++)
    {
        m_aviable.push_back(v_range[i]);
    }
    

    // 测试打印
    for (int i=0; i<v_range.size(); i++)
    {
        cout << v_range[i] << "\t";
    }
    cout << endl;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值