从真值中随机选择STL向量的索引

时间:2013-12-02 16:04:36

标签: c++ arrays c++11 random stl

我的矢量看起来像:

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是非静态的,数千个元素很长。

4 个答案:

答案 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;});