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

  • 相关阅读:
    Windows Azure Cloud Service (14) 使用Windows Azure诊断收集日志记录数据
    Windows Azure Cloud Service (13) 用Visual Studio 2010 将应用程序部署到Windows Azure平台
    Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
    Windows Azure Storage (5) Windows Azure Drive
    Windows Azure Storage (7) 使用工具管理Windows Azure Storage
    SQL Azure(二) SQL Azure vs SQL Server
    webbrowser的自动提交
    提取视频的背景声音的软件
    Listview列排序的bug原因
    两个奇怪的问题
  • 原文地址:https://www.cnblogs.com/forcheryl/p/4707766.html
Copyright © 2011-2022 走看看