zoukankan      html  css  js  c++  java
  • 概率问题总结

    1. 给N张扑克牌和一个随机函数,设计一个洗牌算法 [CC150]

    关键点:如何保证每张牌等概率地出现在每个位置

     伪码如下

    for i in 1…n:
        randomly select a card j from [1,i]
        swap card i with card j

    C++实现

     1 void shuffle(vector<int> cards, int n) {
     2     if (cards.empty()) {
     3         return;
     4     }
     5     srand(time(0));
     6     for (int i = 1; i <= n; i++) {
     7         int j = 1 + rand() % i;        
     8         swap(cards[i - 1], cards[j - 1]);
     9     }
    10 }
    shuffle

    用数学归纳法证明其正确性:

    1. 当N=1时,P(N张牌到任意位置的概率)= 1/N ; 成立

    2. 假设当N = k时成立,那么当N=k+1时,我们只需要判断是否满足每张牌到每个位置的概率都是1/N即可。

    这里我们对于判断“每张牌到每个位置”分成两大部分,三小部分,看它们的概率是否是1/N。即:

    <1> 第k+1张牌到任意位置

    由算法可知,当i=k+1时,从1~i中随机选出一个位置j,将其与i位置的元素互换。
    由此可知,第k+1张牌到任意位置的概率都是相等的,即都是1/(k+1);
    同理可知,<2.1>也得证。即前k张牌到第k+1位置的概率也都是相等的。

    <2> 前k张牌到任意位置

      <2.1> 前k张牌到第k+1位置

      <2.2> 前k张牌到前k个位置(即前k张牌中任一张牌到前k个位置中的任一位置)

    这里需要用到贝叶斯公式,即条件概率。
    这里我们要求的实际上是前k张牌中任一张牌X到前k个位置中的任一位置index的概率,如果等于1/(k+1)即得证。
    令事件A为这张牌X不被换到第k+1位置处,事件B为牌X被换到前k个位置中的某位置index
    已知 P(B|A) = 1/k , P(A) = 1 - (1 / (k+1))
    则 P(B) = P(B|A)*P(A) + P(B|~A)P(~A)
         = 1/k * [1-(1/(k+1))] + 0
    = 1/(k+1)

    拓展: 完美洗牌算法  ref

    2. 如何等概率地从n个数中随机抽出m个数?[CC150]

    变形:如何从1亿个qq号中随机抽出100个qq号?
         如何从一天的query log里随机抽出100个query?

     我们需要保证每个位置都以m/n的概率被取出。【位置:从1-n这所有的数,每个数对应一个位置

     方法:抽签法

     第 i位置(m - k)/(n - i + 1) 的概率决定当前数是否选(其中k为前面已经抽出的数的个数)

    证明:

    第1个位置:被选中的概率为(m - 0)/ (n - 1 + 1) = m/n

    第2个位置:(n-m)/n * (m/(n-1)) + (m/n) * ((m-1)/(n-1)) = m/n

    ...

    总之,我们能保证让每个位置被选中的概率都是m/n. 

    实现的时候可以p=rand(0, 1), 若p>=(m - k)/(n - i + 1)则选择该数,否则不选。

     1 void chooseEvenly(vector<int>& nums, int m) { // (m - k) / (n - i + 1)
     2     int n = nums.size();
     3     int k = 0;
     4     for (int i = 0; i < n; i++) {
     5         int x = rand(1, n - i);
     6         if (x < m - k) {
     7             cout << nums[i];
     8             k++;
     9         }
    10     }
    11 }
    View Code

    follow up: 

    2.1 如果n大小不确定,如何随机抽出k个数

    变形: 输入的是一个数据流,无法预估其大小

    方法:蓄水池采样法   ref

    设置一个k大小的蓄水池,对前k个数直接放入蓄水池,从第k+1个数开始,每个数都以 k/i 的概率放入蓄水池并从池里随机替换出一个数。 

    伪码:

    Init : a reservoir with the size: k
    for i= k+1 to N
        M=random(1, i);
        if( M < k)
         Swap the Mth value and ith value
    end for 
    View Code

    ref1    ref2

    3. 给定一个能够生成0,1两个数的等概率随机数生成器”,如何生成一个产生0,1,2,3的等概率随机数生成器?

     方法:级联法

    两个0,1 随机生成器级联,每次产生两个数,则可能的结果有(0,0), (0,1), (1,0), (1,1),分别映 射到0, 1, 2, 3即可

    follow up:

    3.1 如何用rand7生成rand9?

    两个rand7可以产生49种可能,扔掉后面的4种,保留前45个,并平均分成9份。

    每次产生一个结果时,假如没落在对应区间中就扔掉,否则根据落在哪个区间判断是0~8中哪个。

    3.2 有1枚硬币,以p的概率产生正面,以1-p的概率产生背面,如何利用它产生一个0.5概率的生成器?

    将两枚硬币级联,只保留“正反”,“反正”两种结果,其他两种结果扔掉

    4. A,B,C三人轮流扔硬币,第一个扔到正面的人算赢,问三个人赢的概率分别为多大?

    方法:方程法

    对这种n不确定或有可能无限循环的题,可以考虑化大为小、列方程。

    P(A) = (1/2)^1  + (1/2)^4 + (1/2)^7 + ... 

    P(B) = (1/2)^2  + (1/2)^5  + (1/2)^8 + ... 

    P(C) = (1/2)^3  + (1/2)^6  + (1/2)^9 + ... 

    所以,

     P(B) = 1/2*P(A) ,P(C) = 1/4 * P(A); P(A) + P(B) + P(C) = 1; 

    可得 P(A) = 4/7, P(B) = 2/7, P(C) = 1/7

    5. A有n个硬币,B有n+1个硬币,谁丢的正面多谁赢,问A不输的概率?

    对前n轮而言,有3种情况:A>B, A<B, A=B.

    设P(A>B) = x, P(A == B) = y,由对称性P(A<B) = x,则有2x + y = 1
    现在来看B扔最后一个硬币的情况:
    • 假如之前A>B,则无论怎么扔,A都不会输,最多平. 概率为x
    • 如果A==B,则B扔了正面,A才会输,这是0.5y;则A不输的概率也为0.5y
    • 如果A<B,则无论B怎么扔,A都输
    所以A不输的概率是:x + 0.5y = 0.5 * (2x + y) = 0.5

     

    6. 一个机器人在原点,右边有一个距离为k的点,机器人以p的概率右移一步,1-p概率左移一步, 问经过M步机器人处于k点的概率?

    k步右移,剩下的M - k步一半左移一半右移,所以

    M<k(M - k)%2 == 1 ,则概率为0

    其他情况下:M中选k + (M-k)/2步的概率

    7. 扔硬币直到连续两次出现正面,求扔的期望次数

     假设期望次数是E,我们开始扔,有如下几种情况:
    • 扔到的是反面,那么就要重新扔,所以是0.5*(1 + E)    【从头来过,递归的继续扔,从这时起期望仍是E】
    • 扔到的是正面,再扔一次又反面了,则是0.25*(2 + E)
    • 扔连续两次都是正面,结束,则是0.25*2
    所以递归来看E = 0.5*(1 + E) + 0.25*(2 + E) + 0.25*2,解得E = 6

  • 相关阅读:
    freertos学习
    开源好用的一些库
    一些链接
    电子书链接
    C#:文件的输入与输出(转载20)
    C# 特性(Attribute 转载19)
    C#:异常处理(转载18)
    C#:正则表达式 (转载17)
    C#:预处理器指令(转载16)
    C#:接口和命名空间(Interface和NameSpace 转载15)
  • 原文地址:https://www.cnblogs.com/forcheryl/p/4707766.html
Copyright © 2011-2022 走看看