Random 以一致随机的方式选择子集?

Random 以一致随机的方式选择子集?,random,combinatorics,Random,Combinatorics,问题是: 编写一个方法,从大小为n的数组中随机生成一组m个整数。每个 元素必须具有相同的被选择概率。 这个答案正确吗 我均匀随机地选取第一个整数。 选择下一个。如果它已经存在。我不接受,否则就接受。继续,直到有m个整数。有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

问题是:

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

这个答案正确吗

我均匀随机地选取第一个整数。
选择下一个。如果它已经存在。我不接受,否则就接受。继续,直到有m个整数。

有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]);
   }
}
int[]a=新的int[]{1,2,3,4}
int n=(2*2*2*2)-1;//2^n-1
int items=new Random().nextInt(n);
//如果items是3,那么这是000011,所以我们选择1和2
//如果项目为5,则为000101,因此我们将选择1和3
//等等
对于(int i=0;i
设m为要选择的元素数

对于i=1;i当您选择一个元素(数字)时,请将要选择的原始范围想象为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;
}
int Choose1(列出ELT)
{
var idx=rnd.Next(0,elts.Count);
var elt=elts[idx];
elts.RemoveAt(idx);
返回英语教学;
} 
公共列表选择(int-fromN,int-chooseM)
{
变量范围=新列表();

对于(int i=1;i如果你的选择是随机的,那么按照你描述的方式选择m个项目的概率是1/pow(n,m)。我认为你需要的是1/C(n,m).

刚刚意识到这个过程可能永远不会终止,我们需要一个解决方案,它在理论上肯定会终止。是这样吗?你的意思是每个子集被选择的概率都相等吗?它最终会终止,尽管取决于m和n的大小,可能效率不太高。但你不想要一个随机的子集t、 …您希望选择的元素正好是m…?+1(不久前)我认为您没有正确地编写伪代码,但重复交换向量中刚选择的元素和最后一个未选择的元素的一般想法是合理的……这样您就可以保持选中和未选中元素之间的划分,并且每次都可以使用单个随机数可靠地索引到尚未选择的元素当选元素…我会在我有时间的时候重新检查代码。我可能犯了错误,但是是的,这是一般的想法。我认为这是正确的,但是如果你看到错误,请随意编辑答案。我已经这样做了-概括地说,在维基百科的帮助下,将m的定义方式和循环条件从
I
更改为
I,just意识到这相当于frankc给出的fisher-yates洗牌
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;
}