概率/随机数算法

来源:互联网 发布:农村污水治理数据 编辑:程序博客网 时间:2024/06/01 08:06

0-1等概率问题

问题描述

  • 一个随机数产生器以概率P生成0,以概率(1-P)生成1,怎样生成等概率的0和1?

主要思路

  • 如果用这个产生器产生两个位,出现00的概率为P^2,出现01的概率为P(1-P),出现10的概率为P(1-P),而出现11的概率为(1-P)^2。故而可以用10表示1,01表示0,从而保证生成0和1的概率是相同的。

代码实现

int generate01(int (*func)()) {    if (func == NULL)        return -1;    int num1 = -1;    int num2 = -1;    int ret = -1;    while(num1 != num2){        num1 = func();        num2 = func();        if (num1 == 1 && num2 == 0) {            ret = 1;            break;        } else if (num1 == 0 && num2 == 1) {            ret = 0;            break;        }    }        return ret;}


0-1问题扩展

  • 利用这个随机数生成器,等概率的生成1,2,……,n

主要思路

  • 利用上面实现的等概率生成0-1的生成器,等概率的生成k为二进制的bit,而其表示的整数值X在0~n-1的范围时,输出X+1,否则重复产生。

代码实现

int generateRandomNum(int max) {    if (max < 1) {        return -1;    }    int bit_num = 0, i = 0;    int result = 0;        while((0x01 << bit_num) < max)         ++bit_num;    //while(result > n) {        while(bit_num > i) {            if (generate01())                result |= 0x01 <<bit_num; //result |= 0x01<<i            i++;        }        i = 0;   // }    return result;}

不重复随机数的产生

问题描述

  • 随机产生0~n-1中的k个不重复的随机数。

主要思路

  • 借用蓄水池算法。先定义一个1~n-1的数组,然后从中抽样K个数。

生成给定范围的随机数

问题描述

  • 给定能随机生成整数1~5的函数,写出能随机生成整数1~7的函数

解决思路

  • 产生K个数(k>1),假定产生的数分别为N1,N2,……Nk,则产生的数为:N1-1+(N2-1)*5 + (N3-1)*5^2,……,(Nk-1)*5^(k-1),即产生的数位于(0,5^(k-1))区间呢。然后把区间等分成k分,则产生的随机数位于(0~6),然后+1即可。如果位于K等分的余数范围,则重新执行上述过程。(PS:不用担心余数问题,当K取3时,落到余数范围的概率已经降为6/125,而且余数不会导致概率的问题,只会影响效率。次解法相当于五进制)

代码实现

int generateRandom(int n) {    if (n < 1)        return -1;    unsigned long long result = 0;    for (int i = 0; i < n; i++) {        result += rand5();    }    result /= 5;    return result;}

如何随机选取1000个关键字

问题描述

  • 给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)。如何才能从这个无穷尽的流中随机的选取1000个关键字?

主要思路

  • 利用蓄水池算法。先生成一个大小为1000的数组,将前1000个关键字填入数组中,随后的关键字随机进行交换。

在半径为1的圆中随机选取一点

主要思路

  • 假设圆心(0,0)。在X轴[-1,1],Y轴[-1,1]的正方形内随机选点,然后判断该点是否在圆内。正方形的面积为4,圆形的面积为Pi,故而正方形内的随机点落在圆内的概率为: Pi/4

代码实现

void generatePoint(double*x, double *y, int r){    int base = 10000;        while (pow(*x, 2) + pow(*y, 2) > pow(r, 2)) {        *x = random() % 10000;        *y = random() % 10000;        *x = (2 * r / (*x)) - r;        *y = (2 * r / (*y)) - r;    }}

蓄水池算法

问题描述

  • 从N个数中,随机抽取K个,是的每个数的抽取概率相同,并且事先不知道K的值

主要思想:

  •     保持一个集合(这个集合中的每个数字出现),作为蓄水池,依次遍历所有数据的时候以一定概率替换这个蓄水池中的数字。将前K个元素都放到水库中,然后对之后的第i个元素,以k/i的概率替换掉这个水库中的某一个元素。

方法证明:

  1. 初始情况。水库中k个元素的出现概率都一致,都是1。
  2. 第一步:处理第k+1个元素。分两种情况:① 元素全部都没有替换;② 其中某个元素被k+1元素替换。
    • 对于case ②:第k+1个元素被选中的概率是k/(k+1),故而这个新元素在水库中出现的概率就一定是k/(k+1)。而水库中剩余的元素出现的概率也就是1-P(P为元素被替换的概率)。水库中任意一个元素被替换的概率为:(k/k+1) * (1/k) = 1/(k+1)。而旧元素出现的概率为k/k+1。即旧元素和新元素出现的概率是相等的。
    • 对于case①:当没有元素被替换时,每个元素出现的概率是一样的。具体为:1-P(P为第k+1个元素被选中) = 1 - k/(k+1) = 1/(k+1)
  3.  利用归纳法:
    • 对于第k+i个元素,其中i ∈(0, length-k)。其出现在水库中的概率为k/(k+i)。利用上面的两步可以得出结论。

算法实现:

int impounding_reservoir(int *array,int length, int k) {    if (k <= 0 || array == NULL         || length <= 0 || k > length) {        return 0;    }        int result[k];    int i = 0, j = 0;    srand((unsigned) time(NULL));     for (i = 0; i < k; i++) {        result[i] = array[i];    }           for (i = k; i < length; i++) {        j = random() % length;        if(j < k)            result[j] = array[i];    }           for (i = 0; i < k; i++)        printf("%d ", result[i]);    printf("\n");     return k;}

产生1~400范围内不重复的20个随机数

int * generateRandom(int *array, int num, int start, int end){    int size = end / 32 + end % 32 > 0 ? 1: 0;    int tmp_arr[size] = {0};    int index = 1, count = 0;    srand(time(NULL));    while(count < num){        index += rand() ;        index %= 400 + 1;        if (test_bit(tmp_arr, index)) {            continue;        } else {            set_bit(tmp_arr, index);            array[count] = index;            index = 1;            count++;        }     }    return array;}
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子不正经吃饭怎么办 月经少卵巢早衰怎么办 四个月婴儿厌食怎么办 孩子读书成绩差怎么办 小孩学习记不住怎么办 儿童不爱吃菜怎么办 10儿童不爱吃饭怎么办 儿童不爱吃蔬菜怎么办 婴儿不爱吃饭怎么办啊 初中不爱写作业怎么办 老是不想写作业怎么办 一年级孩子不爱学怎么办 一年级孩子不爱学习怎么办 我不想读书了怎么办 孩子读书读不懂怎么办 一岁多宝宝不吃奶粉怎么办 小孩不讲话怎么办 舌头 看书记不住内容怎么办 看不下去书怎么办 职高读不下去怎么办 小孩不主动说话怎么办 不喜欢自己的儿子怎么办 生了儿子不喜欢怎么办 孩子不愿意去幼儿园怎么办 内向妈妈带孩子怎么办 从小就不爱学习怎么办 孩子老爱玩不爱学习怎么办? 孩子不爱做题怎么办 看书静不下心怎么办 孩子不自觉学习怎么办 不自觉的孩子怎么办 不学习的孩子怎么办 电脑不受老师控制怎么办 儿子不尊重老师怎么办 小孩不喜欢吃蔬菜怎么办 小孩不愿练钢琴怎么办 孩子不喜欢幼儿园老师怎么办 孩子不主动思考怎么办 我初一不想读书怎么办 初中孩子不爱学习怎么办 初一就不想读书怎么办