×

算法练习(8):二项分布(1.1.27)

96
kyson老师的算法之路
2017.08.30 13:44* 字数 2014

本系列博客习题来自《算法(第四版)》,算是本人的读书笔记,如果有人在读这本书的,欢迎大家多多交流。为了方便讨论,本人新建了一个微信群(算法交流),想要加入的,请添加我的微信号:zhujinhui207407 谢谢。另外,本人的个人博客 http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

算法(第4版)

知识点

  • 二项分布的概念

题目

1.1.27 二项分布。估计用以下代码计算binomial(100, 50)将会产生的递归调用次数:

public static double binomial(int N, int k, double p)
{
    if (N == 0 && k == 0)
        return 1.0;
    if (N < 0 || k < 0) 
        return 0.0;
     return (1.0 - p)*binomial(N-1, k, p) + p*binomial(N-1, k-1,p);
}

将已经计算过的值保存在数组中并给出一个更好的实现。


1.1.27 Binomial distribution. Estimate the number of recursive calls that would be used by the code to compute binomial(100, 50). Develop a better implementation that is based on saving computed values in an array.

分析

离散概率分布
在概率论和统计学中,二项分布是n个独立的是/非试验中成功的次数的离散概率分布,其中每次试验的成功概率为p。这样的单次成功/失败试验又称为伯努利试验。实际上,当n=1时,二项分布就是伯努利分布,二项分布是显著性差异的二项试验的基础。

image.png

式中的n为独立的伯努利试验次数,π为成功的概率,(1-π)为失败的概率,X为在n次伯努里试验中出现成功的次数,表示在n次试验中出现X的各种组合情况,在此称为二项系数(binomial coefficient)。
这是高中数学的知识了,但相信大部分人都忘记了吧。那我们再分析一下上面这段话:

伯努利试验(独立重复试验)
伯努利试验(Bernoulli experiment)是在同样的条件下重复地、相互独立地进行的一种随机试验,其特点是该随机试验只有两种可能结果:发生或者不发生。我们假设该项试验独立重复地进行了n次,那么就称这一系列重复独立的随机试验为n重伯努利试验,或称为伯努利概型。单个伯努利试验是没有多大意义的,然而,当我们反复进行伯努利试验,去观察这些试验有多少是成功的,多少是失败的,事情就变得有意义了,这些累计记录包含了很多潜在的非常有用的信息。
设在一次试验中,事件A发生的概率为p(0<p<1),则在n重伯努利试验中,事件A恰好发生 k 次的概率为: [图片上传失败...(image-9081dc-1511361371305)]

随机事件
随机事件是在随机试验中,可能出现也可能不出现,而在大量重复试验中具有某种规律性的事件叫做随机事件(简称事件)。随机事件通常用大写英文字母A、B、C等表示。随机试验中的每一个可能出现的试验结果称为这个试验的一个样本点,记作ωi。全体样本点组成的集合称为这个试验的样本空间,记作Ω.即Ω={ω1,ω2,…,ωn,…}。仅含一个样本点的随机事件称为基本事件,含有多个样本点的随机事件称为复合事件。

独立事件
相互独立事件(independent events):就是事件A(或B)是否发生对事件B(A)发生的概率没有影响,这样的两个事件叫做相互独立事件。
概率公式: P(A * B) = P(A) * P(B)
推导:相互独立事件的公式由条件概率推得:以任意两事件AB为例
P(AB)=P(A)P(B|A)或P(AB)=P(B)P(A|B)
P(B|A)表示A发生的条件下B发生的概率。所以,当AB相互独立时,P(B|A)=P(B)推广到n个任意事件A1、A2、A3……An
P(A1A2A3……An)=P(A1)P(A2|A1)P(A3|A1A2)P(A4|A1A2A3)……*P(An|A1A2A3……A(n-1))

条件概率
条件概率是指事件A在另外一个事件B已经发生条件下的发生概率。条件概率表示为:P(A | B),读作“在B条件下A的概率”。条件概率可以用决策树进行计算。条件概率的谬论是假设 P(A|B) 大致等于 P(B|A)。

排列组合
排列组合是组合学最基本的概念。所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。
排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示。
计算公式:



此外规定0!=1(n!表示n(n-1)(n-2)...1,也就是6!=6x5x4x3x2x1
组合的定义:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。
计算公式:

;C(n,m)=C(n,n-m)。(n≥m)
其他排列与组合公式 从n个元素中取出m个元素的循环排列数=A(n,m)/m=n!/m(n-m)!. n个元素被分成k类,每类的个数分别是n1,n2,...nk这n个元素的全排列数为 n!/(n1!×n2!×...×nk!). k类元素,每类的个数无限,从中取出m个元素的组合数为C(m+k-1,m)。

古典概型
古典概型也叫传统概率、其定义是由法国数学家拉普拉斯 (Laplace ) 提出的。如果一个随机试验所包含的单位事件是有限的,且每个单位事件发生的可能性均相等,则这个随机试验叫做拉普拉斯试验,这种条件下的概率模型就叫古典概型。 在这个模型下,随机实验所有可能的结果是有限的,并且每个基本结果发生的概率是相同的。古典概型是概率论中最直观和最简单的模型,概率的许多运算规则,也首先是在这种模型下得到的。
积事件
概率论术语.事件A交B称为事件A和事件B的积事件,将A∩B或AB称为的积事件,它表示“事件A与B同时发生”这一事件.
和事件
若某事件发生当且仅当事件A发生或事件B发生,事件A与事件B至少有一个发生,则称此事件为事件A与事件B的并事件(或和事件)记作A∪B(或A+B)

然后我们再看题目的代码,我来注释一下

    /**binomial 是二项分布的英文单词写法,
       带的参数中N是实验的次数,k是发生的次数,p是发生一次的概率,
       因此假设发生一次的概率是0.5,那么题目就变成binomial(100, 50,0.5)调用的次数。**/
    public static double binomial(int N, int k, double p)
    {
        //由于每次递归都是N-1,并且k-1,因此这种情况很难出现
        if (N == 0 && k == 0)
            return 1.0;
        //最终应该是会调用这个if
        if (N < 0 || k < 0) 
            return 0.0;
         
         return (1.0 - p)*binomial(N-1, k, p) + p*binomial(N-1, k-1);
    }

这道题目利用的是二项分布的一个推导公式:

N次试验发生K次的概率:P(N,K)=(1-p)f(N-1,k)+p* f(N-1,K-1)。

答案

写个程序来计算调用次数

public class BinomialSample{
    /*使用一个二维数组来存放各项二项分布的概率
    *行代表重复N次试验,列代表发生k次,所以在下面循环条件中需要 j<=i
    */
    public static double[][] binomial(int N,int k,double p){
        double[][] array=new double[N+1][k+1];
        //给二维数组初始化第一列,避免下面执行时出现数组下标越界
        array[0][0]=1.0;
        for(int i=1;i<N+1;i++)
            array[i][0]=array[i-1][0]*(1-p);
        for(int i=1;i<N+1;i++)
            for(int j=1;j<=i && j<k+1;j++)
                array[i][j]=(1-p)*array[i-1][j] + p*array[i-1][j-1];
        return array;
    }
    public static void main(String[] args){
        double[][] array=binomial(100,50,0.25);
        System.out.println(array[100][50]);
    }
}

运行结果:4.507310875086383E-8

代码索引

BinomialSample.java

广告

我的首款个人开发的APP壁纸宝贝上线了,欢迎大家下载。

日记本
Web note ad 1