Generics 根据概率选择赢家的随机数

Generics 根据概率选择赢家的随机数,generics,random,Generics,Random,假设您有一个代表竞争对手及其获奖概率的哈希数组(介于0和1之间的浮动)。比如: 我想有一个算法,我可以选择三个赢家使用随机数,但尊重每个人的概率 样本的总概率为3.3 逻辑方法是计算随机值,如下所示: val = rand(33)/10.0 然后扫描数组,直到我找到那个达到随机数的人 这种方法可行,但它意味着在阵列中进行扫描 我想知道是否会有一个更直接的解决办法。有什么想法吗 PS:想象一下数组可能有大量元素。我在考虑这个问题,我认为我的结果是有意义的: 根据概率对向量排序:[a=0.1,b=

假设您有一个代表竞争对手及其获奖概率的哈希数组(介于0和1之间的浮动)。比如:

我想有一个算法,我可以选择三个赢家使用随机数,但尊重每个人的概率

样本的总概率为3.3

逻辑方法是计算随机值,如下所示:

val = rand(33)/10.0
然后扫描数组,直到我找到那个达到随机数的人

这种方法可行,但它意味着在阵列中进行扫描

我想知道是否会有一个更直接的解决办法。有什么想法吗


PS:想象一下数组可能有大量元素。

我在考虑这个问题,我认为我的结果是有意义的:

  • 根据概率对向量排序:[a=0.1,b=0.2,c=0.3,d=0.4]
  • 选择一个随机数(例如0.5)
  • 从头开始迭代,将概率值求和,当概率值较高时停止: 答案=0.1+0.2+0.3。因此,0.6>0.5,我们计算‘c’
  • 我的要点是向量末尾的值应该有更高的被选择的概率。我已经用python实现了:

    values = [0.1,0.2,0.3,0.4]
    count_values = len(values)*[0]
    answer = len(values)*[0]
    
    iterations = 10000 
    
    for i in range(0,iterations):
        rand = float(random.randint(0,iterations))/iterations
        count = 0
        sum = 0
        while sum <= rand and count <= len(values):
            sum += values[count]
            count += 1
        count_values[count-1]+=1
    
    for i in range(0,len(count_values)):
        answer[i] = float(count_values[i])/iterations
    

    我假设在你的例子中,“概率”意味着“权重”(因此概率为1.0的人不一定会赢,总概率总和也不会达到1.0)

    您可以构建一个节点树,其中叶节点包含您的单个条目:

    leaf1 = {:name => "Adam" , :prob => 0.5}
    leaf2 = {:name => "Ben" , :prob => 1.0}
    
    每个节点都包含它下面的节点的总和

    node1 = { :prob_sum => 1.5 , :children=> [ leaf1, leaf2] }
    
    然后,根节点包含整个结构的总和

    root_node = { :prob_sum => 33 , :children => [ leaf9, leaf10] }
    
    然后在0和根节点中包含的和之间选择一个随机数

    my_random = rand( root_node.prob_sum )
    
    然后穿过这棵树。每个节点都包含其下所有节点的总和,因此如果随机数大于该节点,则减去该节点的值并跳过该分支

    def find_node( my_random ):
    c = children.first()
    while( c ):
         if ( c.prob_sum < my_random ):
             return c.find_node(my_random)
         my_random -= c.prob_sum
         c = c.next
    
    def find_节点(my_random):
    c=儿童。第一个()
    而(三):
    如果(c.prob_sum
    假设您已经构建了一个平衡树,您应该在O(logn)中得到结果


    或者,您可以通过向当前数据集中添加一个“运行总计”字段并基于该“运行总计”进行二进制搜索来获得相同的结果。这可能更容易实现,但只有当您的工作集可以放在内存中时才适用。

    还有一种方法目前仍在使用,但存在一些问题

    今天,我创建了一个数组,并为该数组中的每个人输入概率*100个条目

    然后可以直接对数组内容执行随机操作

    第一个问题是,它在各个方面(内存、处理等)都很昂贵,而且无法扩展

    第二个问题是,当我选择第二个和第三个人物时,我要么把第一个人物拿出来,要么随机循环,直到另一个人被选中


    尽管如此,对于小数据集(如我到目前为止所做的,但会随着时间的推移而增加),此解决方案工作得很好。

    创建一个循环,该循环将一直运行到选择3个优胜者为止。在这个循环中,使用您选择的编程语言中可用的任何随机方法生成特定的随机数。之后,开始遍历用户。如果任何用户的概率小于此随机数,则接受该用户为赢家。如果在循环的任何迭代中没有选择赢家,例如,在列表中的最低概率为0.2且生成的随机数为0.1的情况下,在这种情况下,继续循环的下一次迭代。当你获得3名优胜者时,打破循环。可能的伪代码如下所示:

    int count=0;
    while(count<3){
        temp=GenerateRandomNumber()
        int userIndex= AcceptWinner(UserListProbability,temp)
        //here keep iterating through the users to check which user's probability is less than temp and returns the index of the winner in the List
    
        if(userIndex==-1)//No winner selected
            continue;
        else{
            count++;
            Print List(userIndex)
        }
    }
    
    int count=0;
    
    虽然(countI在下面发布了我的解决方案,但是,考虑到你处理的是概率,我认为所有概率的总和应该等于1。在你的例子中,Ben有100%的几率被选中。是的,你是对的。只是我实际上使用了配额的概念,为了简化问题,我将配额改为0我实际上很喜欢你的第二种方法,把运行总数相加,然后进行二进制搜索,因为在系统中,“权重/概率”因为每个人都会随着时间的推移而变化,我需要重建树。对于有序表,我只需要保持它们的有序。谢谢。我只是不明白为什么要对向量进行排序?不进行排序,这就是我在问题中提到的方法。谢谢。因为我们求和权重,例如,如果它们没有排序,则概率最高刚开始的时候(如0.6),永远不会选择较小的(如0.1)。无论如何,测试一万次此处发布的所有解决方案,看看它们是否正确,结果必须与概率匹配。这里的复杂性也是O(n)
    def find_node( my_random ):
    c = children.first()
    while( c ):
         if ( c.prob_sum < my_random ):
             return c.find_node(my_random)
         my_random -= c.prob_sum
         c = c.next
    
    int count=0;
    while(count<3){
        temp=GenerateRandomNumber()
        int userIndex= AcceptWinner(UserListProbability,temp)
        //here keep iterating through the users to check which user's probability is less than temp and returns the index of the winner in the List
    
        if(userIndex==-1)//No winner selected
            continue;
        else{
            count++;
            Print List(userIndex)
        }
    }