8

在我的算法中,我有两个值需要随机选择,但每个值都必须选择预定的次数。

到目前为止,我的解决方案是将选择正确次数放入向量中,然后对其进行洗牌。在 C++ 中:

// Example choices (can be any positive int)
int choice1 = 3; 
int choice2 = 4;

int number_of_choice1s = 5;
int number_of_choice2s = 1;

std::vector<int> choices;
for(int i = 0; i < number_of_choice1s; ++i) choices.push_back(choice1);
for(int i = 0; i < number_of_choice2s; ++i) choices.push_back(choice2);
std::random_shuffle(choices.begin(), choices.end());

然后我保留一个迭代器choices,每当我需要一个新的迭代器时,我都会增加迭代器并获取该值。

这可行,但似乎可能有更有效的方法。因为我总是知道我将使用每个值的多少,所以我想知道是否有更算法的方法来执行此操作,而不仅仅是存储值。

4

3 回答 3

10

您不必要地使用了这么多内存。你有两个变量:

int number_of_choice1s = 5;
int number_of_choice2s = 1;

现在简单地随机化:

int result = rand() % (number_of_choice1s + number_of_choice2s);
if(result < number_of_choice1s) {
  --number_of_choice1s;
  return choice1;
} else {
  --number_of_choice2s;
  return choice2;
}

这可以很好地扩展两百万次随机调用。

于 2012-05-10T20:02:26.617 回答
1

你可以写得更简单一点:

std::vector<int> choices(number_of_choice1s, choice1);
choices.resize(number_of_choice1s + number_of_choice2s, choice2);
std::random_shuffle(choices.begin(), choices.end());
于 2012-05-10T20:40:33.317 回答
0

有偏差的随机分布将在结果集上保持某种顺序(选择最多的选择接下来被选择的机会越来越少),这会产生有偏差的结果(特别是如果您必须选择的次数第一个值比第二个值大,你最终会得到类似 {1,1,1,2,1,1,1,1,2} 的东西。

这是代码,它看起来很像@Tomasz Nurkiewicz 编写的代码,但使用简单的偶数/奇数应该有大约 50/50 的机会选择任一值。

int result = rand();

if ( result & 1  &&  number_of_choice1s > 0)
{
number_of_choice1s--;
return choice1;
}else if (number_of_choice2s>0)
{
number_of_choice2s--;
return choice2;
}
else
{
return -1;
}
于 2012-05-10T22:01:59.553 回答