我正在尝试了解以下任务的解决方案:从大小为N的数组中随机生成一组M个元素。每个元素的选择概率必须相同。
我找到了以下解决方案(我已经读过这个问题,但是它不能回答我的问题):
int rand(Random random, int min, int max) {
return random.nextInt(1 + max - min) + min;
}
char[] generateArray(char[] original, int subsetSize) {
char[] subset = new char[subsetSize];
Random random = new Random();
for (int i = 0; i < subsetSize; i++) {
subset[i] = original[i];
}
for (int i = subsetSize; i < original.length; i++) {
int r = rand(random,0, i);
boolean takeIthElement = r < subsetSize;
if (takeIthElement) {
subset[r] = original[i];
}
}
return subset;
}
// rand() function returns inclusive value
// i.e. rand(0, 5) will return from 0 to 5
可以在“破解编码访谈”一书中找到此代码(Section Hard,任务3)。作者解释如下:
假设我们有一种算法可以m从size数组中提取随机元素集n - 1。我们如何使用该算法m从大小数组中提取随机元素集n?我们首先可以从前几个n - 1元素中随机抽取大小为m的集合。然后,我们只需要确定是否array[n]应将其插入子集即可(这将需要从子集中抽出一个随机元素)。一种简单的方法是从0到n中选择一个随机数k。如果k < m,然后插入array[n]到subset[k]。这都将“公平地”(即具有成比例的概率)插入array[n]进入子集并“公平地”从子集中删除随机元素。迭代编写甚至更干净。在这种方法中,我们将数组子集初始化为m原始数组中的第一个元素。然后,我们遍历数组,从element开始,每当m插入array[i]到(随机)位置的子集中。kk < m
我想作者想说我们需要生成的不是set,而是数组。所以,我认为正确的任务描述应该是:随机产生一个阵列M个元素的大小从N的一个阵列的每个元素必须具有被选择的同等概率。
如果为true,则上述代码将无法正常工作。原因:
例如,我们有一个数组{'1', '2', 'a', 'b'}和m = 2
因此,我们应该具有生成以下几组的资格概率:
{1, 2}; {2, 1}; {1, a}; {a, 1}; {1, b}; {b, 1}; {a, 2}; {2, a}; {b, 2}; {2, b}; {a, b}; {b, a}
我在这里担心的是,该函数将永远不会生成以下集合: {2, 1}; {2, a}; {2, b}
因此,这意味着它是不正确的。
LEATH
小怪兽爱吃肉
守着星空守着你
相关分类