【发布时间】:2020-11-20 17:44:45
【问题描述】:
我想在{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。
【问题讨论】:
-
我知道您仅限于 C++11,但是当您升级到 C++17 时,请参阅目标上的第二个答案。
-
谁结束了这个问题?链接的问题对我的问题没有适当的答案。
shuffle洗牌整个范围!请重新打开。 -
您始终可以使用@ ping 问题的更近者。我不跟。除了你要采样 3 个值,而目标要采样 4 个之外,为什么你认为这不是一个骗局?
-
被标记的副本将整个范围洗牌,从中提取前 N 个值(就像洗一副牌,然后取前 N 个)。当您只需要少量值时,它在计算上会比我建议的答案更昂贵。
-
@1201ProgramAlarm 目标可能有更好的答案这一事实并不意味着这不是重复的。如果它比其他解决方案更好,您可以在那里发布您的答案。据我所知,这两个问题都在问同一个问题。