zoukankan      html  css  js  c++  java
  • 一个很nice的随机数列产生函数

    在编程珠玑里面看到的,原来一直使用的是下面这种方法。

    -------------------------------------------------------------------

    产生一组不重复的随机数。

    在网上查了查,看到了一个完美的解决方案。

    http://madongfly.blogspot.com/2008/12/blog-post.html

    for(i = 0; i < n; i++) {
        x[i] = i;
    }
    for(i = 0; i < k; i++) {
        t = rand(i, n-1);
        swap(x[i], x[t]);
        out(x[i]);
    }
    

    其中,rand(a,b)产生一个 a 到 b 之间的随机数,swap(a,b)交换a和b的值,out(a)把a输出作为结果。
    我们来看看这个算法的完美之处吧!

    首先,x数组里把0到n-1的所有数都存储了,而最后输出的都是x数组里的值,所以满足输出的数是k个0到n-1的数。

    然后,我们对于第 i 次随机,产生一个 i 到 n-1 的下标 t ,并把x[t] 和x[i]交换,将其输出,这样每次产生的数都是之前没有出现过的数,因为之前出现过的数都在x[0] 到 x[i-1]里呢!这样就保证了输出数据的不重复性。

    最后,我们考察输出数据的“随机性”,显然,因为交换操作,使得所有没有出现过的数都在x[i] 到 x[n-1]中存着呢,所以被选中的概率相等。

    --------------------------------------------------------------------------

    上面这种方法的缺点是空间是O(n),比如n是1亿,那么你就要开辟一个1亿的数组,浪费空间。

    下面这种方法比较适合产生随机序列,而且使用的是set,默认是升序。

    set<int> a;
    void gen(int n, int m) {
        a.clear();
        int t ;
        for(int j = n - m ;j < n;j++){
            t = rand() % (j+1);
            if (a.find(t) == a.end() ){
                a.insert(t);
            }
            else a.insert(j);
        }
    }
    
  • 相关阅读:
    .net注册iis
    hdu 1081To The Max
    hdu 1312Red and Black
    hdu 1016Prime Ring Problem
    hdu 1159Common Subsequence
    hdu 1372Knight Moves
    hdu 1686Oulipo
    hdu 1241Oil Deposits
    hdu 1171Big Event in HDU
    hdu 4006The kth great number
  • 原文地址:https://www.cnblogs.com/iammatthew/p/1825798.html
Copyright © 2011-2022 走看看