![](/img/trans.png)
[英]C++ randomly sample k numbers from range 0:n-1 (n > k) without replacement
[英]Sample 3 integers without replacement in C++
我想在不替换的情况下对{0, 1, ..., n-1}
三个整数进行采样。
到目前为止,我是这样进行的:
#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};
}
这有效,但有更好的方法吗?
我想在循环中多次执行此采样。 为每次迭代重新定义采样器是否耗时?
由于技术原因,我只能使用 C++ 11。
您可以在不分配任何额外内存的情况下从0, ..., n - 1
进行无替换采样; elem
是不需要的。 关键是模拟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};
}
您可以用最后一个元素替换从向量中选择的元素,而不是使用erase
。
elems[i1] = elems[n - 1];
然后对第二个做同样的事情:
elems[i2] = elems[n - 2];
构建三个uniform_int_distribution
的时间是最少的。 构建elems
会消耗更多时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.