生成不重复随机数的方法

问题描述:
给定一个n,一个m
要求在1 ~ n这n个数字中,生成m个不重复的随机数。

思路:
生成随机数大家都知道,C++中也提供了相关的函数——rand()。
但是问题中要求生成的是无重复的随机数,这里就需要对生成的随机数进行去重操作了。

首选最直观的思路是可以使用set,利用set的无重复的性质对数字进行过滤。
算法如下:

    while (s.size() < m) {
        s.insert(rand() % n + 1);       //取随机数取模,由于从1开始,故后面+1
    }

那么,出了set之外,是否还有其他思路呢?

举个例子,对于1,2,3,4,5这五个数字来说,取两个随机数,那么我们可以模拟整个取数的过程。
首先对于数字1,取1 的概率为2/5.
对于数字2,则要分为两种情况:
1.数字1已经取到,那么在这个前提下,剩下4个数字取一个即可,每个数字被取到的概率是1/4
2.数字1未被取到,那么这个问题就缩小为在2~4这4个数字中,取2个数字,此时的2被取到的概率为2/4。

以此类推,我们可以对整个取数字的过程进行模拟。

    for (int i = 1; i <= n; ++i) {
        //例如,n = 5, m = 2时
        //在刚开始,第一次抽的时候,数字1被抽中的概率为2/5
        if (rand() % (n-i+1) < num) {           //抽中的情况
            cout << i << " ";       //此时i被抽中,输出i
            --num;
        }
        if (!num)
            break;              //取够了的情况
    }

那么,还有没有其他的思路呢?答案是有的。

既然要求随机,那么对于乱序的1~n的数字,直接输出前m项,即为所求。
于是我们可以将数组存入数组中对其乱序,输出前m项便可得到结果。

//Algorithm 3
//将数组乱序后输出前m项即可

    int *arr = new int[n];
    for (int i = 0; i < n; ++i)
        arr[i] = i + 1;
    for (int i = 0; i < m; ++i) {
        int temp = rand() % n;
        swap(arr[i], arr[temp]);
    }

整体代码如下。

// 随机数生成.cpp : 定义控制台应用程序的入口点。
//
//从1~n这个数字中生成m个不重复的数字
#include "stdafx.h"
#include <iostream>
#include <set>
#include <algorithm>
#include <cstdlib>
using namespace std;
int main()
{
    //Algorithm 1
    //模拟抽取的过程,结果为有序
    int n, m;
    cin >> n >> m;
    int num = m;
    for (int i = 1; i <= n; ++i) {
        //例如,n = 5, m = 2时
        //在刚开始,第一次抽的时候,数字1被抽中的概率为2/5
        if (rand() % (n-i+1) < num) {           //抽中的情况
            cout << i << " ";       //此时i被抽中,输出i
            --num;
        }
        if (!num)
            break;              //取够了的情况
    }
    cout << endl;

    //Algorithm 2 
    //使用set过滤
    set <int> s;
    while (s.size() < m) {
        s.insert(rand() % n + 1);       //取随机数取模,由于从1开始,故后面+1
    }
    for (auto iter = s.begin(); iter != s.end(); ++iter)
        cout << *iter << " ";
    cout << endl;

    //Algorithm 3 
    //将数组乱序后输出前m项即可

    int *arr = new int[n];
    for (int i = 0; i < n; ++i)
        arr[i] = i + 1;
    for (int i = 0; i < m; ++i) {
        int temp = rand() % n;
        swap(arr[i], arr[temp]);
    }
    sort(arr, arr + m);
    for (int i = 0; i < m; ++i)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

运行结果如下。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/h4329201/article/details/80422996