zoukankan      html  css  js  c++  java
  • Algorithm | Random

    随机生成[0,n)中不重复的m个数。

     1 class Random {
     2 public:
     3     Random(int n, int m):n(n), m(m) {}
     4     void generate() {
     5         srand(time(NULL));    
     6         for (int i = 0; i < n; ++i) data.push_back(i);
     7         for (int i = 0; i < m; ++i) swap(data[i], data[i + rand() % (n - i)]);
     8     }
     9 
    10     void increase() {
    11         data.push_back(n++);
    12         int i = rand() % n;
    13         swap(data[i], data[n - 1]);
    14     }
    15 
    16     void print() const {
    17         for (int i = 0; i < m; ++i) 
    18             cout << data[i] << " ";
    19         cout << endl;
    20     }
    21 private:
    22     int n;
    23     int m;
    24     vector<int> data;
    25 };

    Line 7, 第i个元素会和第从[i, n)中找一个元素交换。可以证明每个数被选择在第k个位置上的概念为1/n。被选择的概念为m/n。

    比如0被放在data[1]这个位置的概率,等于0没有被放在第一个位置的概率*0放在第二个位置的概率,也就是(1-1/n)*1/(n-1)=1/n。

    依此类似。

    最终前m个数就是不重复随机数。

    如果data是不断递增的,也就是newN = n + 1,怎么随机选择k个数? 只要将data[newN - 1]和前面的数随机交换就可以了,O(1)的更新。

    对于第newN个数,它被选上的概率是1/newN.

    其他数被选上的概率 =(它之前被选在m个数里面的概率)*(它在newN下没有被交换出这m个数的概率)

    =(它之前被选在m个数里面的概率)*(第newN个数和其他数交换的概率)=(1/n)*(n/newN)=1/newN。

    Select a random number from stream, with O(1) space

    Given a stream of numbers, generate a random number from the stream. You are allowed to use only O(1) space and the input is in the form of stream, so can’t store the previously seen numbers.

    So how do we generate a random number from the whole stream such that the probability of picking any number is 1/n. with O(1) extra space? This problem is a variation of Reservoir Sampling. Here the value of k is 1.

    看完geeksforgeeks上面的解释。

    重写了一遍。

    1     void increase() {
    2         data.push_back(n++);
    3         int i = rand() % n;
    4         //swap(data[i], data[n - 1]);
    5         if (i < m) data[i] = data[n - 1];
    6     }
  • 相关阅读:
    PostgreSQL数据库逻辑复制实践
    CentOS7通过yum安装postgreSQL
    MongoDB动态建表方案(官方原生驱动)
    7大常用开源数据库利弊全对比
    错误:由于系统时间错误证书验证失败导致更新不成功
    deppin更新提示“由于没有公钥,无法验证下列签名”
    Debian 9 Vim无法使用鼠标右键复制 解决方法
    PHP版滑动时间窗口算法
    RabbitMQ PHP 代码示例
    创建或修改 docker 容器内部文件
  • 原文地址:https://www.cnblogs.com/linyx/p/3770466.html
Copyright © 2011-2022 走看看