【问题标题】:Choosing a subset in uniformly random manner?以均匀随机的方式选择一个子集?
【发布时间】:2011-06-06 11:55:01
【问题描述】:

问题是:

编写一个方法,从一个大小为 n 的数组中随机生成一组 m 个整数。每个 元素被选中的概率必须相等。

这个答案正确吗?:

我随机选择第一个整数。 选择下一个。如果它已经存在。我不接受,别人接受。并继续直到我有 m 个整数。

【问题讨论】:

  • 刚刚发现这个过程可能永远不会终止,我们想要一个解决方案,理论上肯定会终止。是这样吗?
  • 你的意思是每个子集被选中的概率相等吗?
  • 它总是会最终终止,尽管取决于 m 和 n 的大小,可能效率不高。

标签: random combinatorics


【解决方案1】:
设 m 为要选择的元素数 对于 i = 1;我

在循环结束时,数组的最后 m 个元素是您的随机子集。 Fisher-yates shuffle 有一个变化。

【讨论】:

  • +1(不久前)我认为您没有正确编写伪代码,但是将刚刚选择的元素与最后一个未选择的元素重复交换的一般想法矢量是合理的......这样你就维护选定元素和未选定元素之间的划分,并且每次都可以使用单个随机数来可靠地索引到尚未选择的元素.. ..
  • 我会在有时间的时候重新检查代码。可能我犯了一个错误,但是是的,这是一般的想法
  • 我认为这是对的,但如果您发现错误,请随时编辑答案
  • 我已经这样做了——总而言之,将 m 的定义方式和循环条件从 i < m 更改为 i <= m...如果您不同意,请随时再次更改......跨度>
【解决方案2】:

有 2^n 个子集。选择一个介于 0 和 2^n-1 之间的数字并将其转换为二进制。那些设置了位的应该从数组中取出并存储。

例如考虑集合 1,2,3,4。

int[] a = new int[]{ 1, 2, 3, 4 }
int n = (2*2*2*2) - 1; // 2^n -1 
int items = new Random().nextInt(n);

// If items is 3 then this is 000011 so we would select 1 and 2
// If items is 5 then this is 000101 so we would select 1 and 3
// And so on
for (int i=0;i<a.length;++i) {
   if ((items & (1 << i)) != 0) {
       // The bit is set, grab this item
       System.out.println("Selected " + a[i]);
   }
}

【讨论】:

  • 但是您不想要一个随机子集...您希望恰好选择 m 个元素...?
【解决方案3】:

将要从中选择的原始范围视为 1-n 的列表,当您选择一个元素(数字)时,从列表中删除该元素。根据列表索引选择元素,而不是实际的数值。

int Choose1(List<int> elts)
{
    var idx = rnd.Next(0,elts.Count);
    var elt = elts[idx];
    elts.RemoveAt(idx);
    return elt;
} 

public List<int> Choose(int fromN, int chooseM)
{
    var range = new List<int>();
    for (int i = 1; i <= fromN; i++)
    {
        range.Add(i);
    }
    var choices = new List<int>();
    for (int i = 0; i < chooseM; i++)
    {
        choices.Add(Choose1(range));
    }
    return choices;
}

使用列表对大数而言效率不高,但您可以使用相同的方法,而无需实际构造任何列表,只需使用一点算术。

【讨论】:

  • 在wikipedia的帮助下,才意识到这相当于frankc给出的fisher-yates shuffle
【解决方案4】:

如果您的选择是随机的,那么以您描述的方式选择 m 个项目的概率将为 1/pow(n,m)。我认为你需要的是 1/C(n,m)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    相关资源
    最近更新 更多