根据大小为N

时间:2018-07-07 18:07:25

标签: java arrays random set probability

我正在尝试了解以下任务的解决方案: 从大小为N的数组中随机生成一组M个元素。每个元素的选择概率必须相同。

我找到了以下解决方案(我已经读过this questionthis one,但是我仍然有一些问题太长,无法发表评论):

int rand(int min, int max) { 
  return min + (int)(Math.random() * (max - min + 1));
}

int[] generateSet(int[] arr, int m, int n) {
    if (n + 1 == m) { //base case
        int[] set = new int[m];
        for (int k = 0; k < m; k++) {
            set[k] = arr[k];
        }
        return set;
    }

    int[] set = generateSet(arr, m, n - 1);
    int r = rand(0, n);
    if (r < m) set[r] = arr[n];
    return set;
}
// rand() function returns inclusive value 
// i.e. rand(0, 5) will return from 0 to 5

此代码可在“破解编码访谈”一书中找到(硬性部分,任务3)。 作者解释如下:

  

假设我们有一个算法可以从大小为m的数组中提取n - 1个元素的随机集合。我们如何使用该算法从大小为m的数组中提取n个元素的随机集合?我们首先可以从前n - 1个元素中提取大小为m的随机集。然后,我们只需要确定是否应将array[n]插入子集(这将需要从中抽出一个随机元素)。一种简单的方法是从0到n中选择一个随机数k。如果为k < m,则将array[n]插入subset[k]中。这样既可以“公平地”(即,具有成比例的概率)将array[n]插入子集中,也可以“公平地”从子集中删除随机元素。   迭代编写甚至更干净。在这种方法中,我们将数组子集初始化为原始数组中的前m个元素。然后,我们遍历数组,从元素m开始,每当array[i]时将k插入(随机)位置k < m的子集中。

我完全理解基本情况。它说:如果我们有一个大小为NM == N的数组,那么,我们应该从该数组中返回第一个M元素,因为每个都将以相等的概率被选中。

比我根本不了解的困难部分(递归情况)

  1. 代码从大小为M的数组中生成大小为N - 1的集合
  2. 现在,代码应决定是否向集合中添加“ {new}”元素arr[N]
  3. 代码由M / N概率决定添加或不添加“新”元素。随机工作如下:

    1. r0之间生成随机数N
    2. 如果(r < m)表示r的产生概率为M / N
    3. 如果(r < m)也意味着我们将以概率1 / M更改集合中M个元素之一。

更新:

我不理解以下内容: 想象一下,我们有一个包含N-1个元素的盒子。我们从中获取M个元素。因此,获得一组元素的可能性为:

Pa(get any set with M elements using N-1 elements) = 1 / ((N-1)! / M!(N-1-M)!) = M!(N-1-M)!) / (N-1)!

很明显,如果我们将所有元素放回框中,而不是再次获取M元素,我们将始终以相同的概率创建一个集合。

好吧,让我们假设我们采用了M个元素。因此,box现在包含N-1-M个元素。

因此,这是递归情况开始的地方: 现在我们从口袋里拿出一个新元素。现在,我们应该决定是否修改集。

从这一点开始,我完全不知道下一步该怎么做。我的猜测:

当我们有N-1个元素时,生成具有M个元素的任何集合的概率为:

Pa(get any set with M elements using N-1 elements) = M!(N-1-M)!) / (N-1)!

但是我们又添加了一个新元素。现在我们应该生成任何M元素集,其概率必须等于Pa。 但是现在新的可能性将是:

Pb = 1 / (N! / !M(N-M)!) = M!(N-M)!) / N!

所以我们需要找到一种方法,以某种方式将Pb转换为Pa,即

!M(N-M)!) / N!!M(N-1-M)!) / (N-1)!

使用一些魔术(我仍然不知道它是如何工作的)递归案例来做到这一点:

  1. 致电R = rand(0,X)(我不知道X是什么)。如果R等于某个Y(我不知道Y值是多少),则意味着我们应该使用新元素。

  2. 如果R等于Y,则调用rand(0,M)生成将使用新元素更新的索引

问题: 1.如何计算X和Y值?

1 个答案:

答案 0 :(得分:1)

choose(n, m) = n! / (m! (n-m)!)种方法可以从包含m个元素的集合中选择n个元素。您想以均等的概率选择这些安排中的任何一种。

关于是否采用给定元素not有两种选择:

  1. 选择“ this”元素,然后从m-1个元素中选择n-1个元素;
  2. 还是不选择“ this”元素,而不是从m元素中选择n-1元素。

您必须做出选择,才能产生频率相等的任何安排

P(pick) = (# arrangements which pick "this" element) / (# arrangements)
        = (# arrangements which pick "this" element) / (# arrangements which pick "this" element + # arrangements which do not pick "this" element)
        = A / (A + B)

为方便起见,引入了AB

A = choose(n-1, m-1) 
  = (n-1)! / (m-1)!(n-m)!

B = choose(n-1, m) 
  = (n-1)! / m!(n-m-1)!

AB的分子和分母相乘,使它们的公因数为(n-1)! / m!(n-m)!

A = m     * (n-1)! / m!(n-m)!
B = (n-m) * (n-1)! / m!(n-m)!

然后:

P = m / (m + n - m)
  = m / n

根据需要。