[英]Sample 3 integers without replacement in C++
I want to sample three integers among {0, 1, ..., n-1}
without replacement.我想在不替换的情况下对
{0, 1, ..., n-1}
三个整数进行采样。
Here is how I proceed so far:到目前为止,我是这样进行的:
#include <random>
/* constructs vector {0, 1, ..., n-1} --------------------------------------- */
template <class T>
std::vector<T> integers_n(T n) {
std::vector<T> out(n);
for(T i = 0; i < n; i++) {
out[i] = i;
}
return out;
}
/* samples three integers among {0, 1, ..., n-1} ---------------------------- */
const std::vector<int> choose3(const int n,
std::default_random_engine& generator) {
std::uniform_int_distribution<int> sampler1(0, n - 1);
std::uniform_int_distribution<int> sampler2(0, n - 2);
std::uniform_int_distribution<int> sampler3(0, n - 3);
const int i1 = sampler1(generator);
const int i2 = sampler2(generator);
const int i3 = sampler3(generator);
std::vector<int> elems = integers_n(n);
elems.erase(elems.begin() + i1);
const int j2 = elems[i2];
elems.erase(elems.begin() + i2);
const int j3 = elems[i3];
return {i1, j2, j3};
}
This works but is there a better way?这有效,但有更好的方法吗?
I want to perform this sampling multiple times, in a loop.我想在循环中多次执行此采样。 Is it time-consuming to redefine the samplers for each iteration?
为每次迭代重新定义采样器是否耗时?
For technical reasons, I am restricted to C++ 11.由于技术原因,我只能使用 C++ 11。
You can sample without replacement from 0, ..., n - 1
without allocating any additional memory;您可以在不分配任何额外内存的情况下从
0, ..., n - 1
进行无替换采样; elem
is unneeded. elem
是不需要的。 The key is to simulate a few steps of the Fisher-Yates Shuffle , as seen in David Eisenstat's answer to my related question .关键是模拟Fisher-Yates Shuffle的几个步骤,如David Eisenstat 对我的相关问题的回答所示。
// std::array<int, 3> requires no heap allocation, so is a better choice.
std::array<int, 3> choose3(const int n,
std::default_random_engine& generator) {
std::uniform_int_distribution<int> sampler1(0, n - 1);
std::uniform_int_distribution<int> sampler2(0, n - 2);
std::uniform_int_distribution<int> sampler3(0, n - 3);
// Algorithm translated from https://stackoverflow.com/a/64359519/1896169
int i1 = sampler1(generator);
int i2 = sampler2(generator);
int i3 = sampler3(generator);
if (i3 == i2) i3 = n - 2;
if (i3 == i1) i3 = n - 1;
if (i2 == i1) i2 = n - 1;
return {i1, i2, i3};
}
Rather than using erase
, you can replace the element chosen from the vector by the last element.您可以用最后一个元素替换从向量中选择的元素,而不是使用
erase
。
elems[i1] = elems[n - 1];
Then do the same for the second:然后对第二个做同样的事情:
elems[i2] = elems[n - 2];
The time to construct the three uniform_int_distribution
is minimal.构建三个
uniform_int_distribution
的时间是最少的。 Constructing elems
will consume more time.构建
elems
会消耗更多时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.