我的矢量看起来像:
vector<int> A = {0, 1, 1, 0, 0, 1, 0, 1};
我想从A
的非零值中选择一个随机索引。使用此示例A
,我想从数组{1,2,5,7}
中随机选择一个元素。
目前我通过创建另一个数组
来做到这一点vector<int> b;
for(int i=0;i<A.size();i++)
if(A[i])
b.push_back(i);
创建b
后,我会使用以下答案找到索引:
get random element from container
是否有更多类似STL(或C ++ 11)的方法,可能是一个不创建中间数组的方法?在这个例子中,A
很小,但在我的生产代码中,这个选择过程是在一个内循环中,A是非静态的,数千个元素很长。
答案 0 :(得分:5)
执行此操作的好方法是Reservoir Sampling。
简而言之,您将遍历数组,直到找到第一个非零值,并将该索引记录为您可能返回的第一个可能答案。
然后,你继续走数组。每当您发现非零值时,您随机可能更改哪个新索引是您可能的答案,但概率会降低。
如果你需要来自数组的M个随机索引值,这个算法也很有用。
有什么好处的,就是你只走一次每个元素,而你不需要一个单独的记忆结构来记录非零元素。速度为O(N),内存为O(M),在您的情况下,它在内存中为O(1),因为您只需要1个随机值。
另一方面,随机数发生器传统上很慢。因此,您可能希望针对人们在此提出的任何其他想法进行性能测试,以了解速度与内存的权衡对您是否值得。
答案 1 :(得分:2)
通过一次遍历数组,您可以确定有多少假(或真)值。如果你经常这样做,你甚至可以写一堂课来跟踪这个。
无论如何,您可以在0和num_false(或num_true)之间选择一个随机数i
。然后通过另一个数组传递,您可以返回i
假(或真)索引。
答案 2 :(得分:1)
我们可以遍历每个非零值并为其分配一个随机数。具有最大随机数的索引是我们选择的索引。
int value = 0;
int index = 0;
while(int i = 0; i < A.size(); i++) {
if(!A[i]) continue;
auto j = rand();
if(j > value) {
index = i;
value = j;
}
}
答案 3 :(得分:0)
vector<int> A = {0,1,1,0,0,1,0,1};
random_shuffle(A.begin(),A.end());
auto it = find_if(A.begin(),A.end(),[](const int elem){return elem;});