如何以加权方式选择随机数

时间:2014-11-05 07:05:05

标签: java algorithm random

例如,如果我有这样的一组int:

int[] list = {1, 4, 2};

我想选择这3个数字中的一个,但是更频繁地选择更高的值:

1 get chosen 1/7 of the time
4 gets chosen 4/7 of the time
2 gets chosen 2/7 of the time

如果Java中还没有函数,我怎么能为此编写函数。

编辑:我正在寻找一个有效的解决方案,O(n)或更好。

我将在很多线程中多次运行此代码。建立新的清单是不够的。

3 个答案:

答案 0 :(得分:3)

累计列表中的值并调用结果总和S。现在生成一个从0到S - 1的随机数。在list上再次迭代,并为每个元素执行以下操作:如果元素大于S,则选择该元素。否则,按元素值减少S并继续下一个元素。

答案 1 :(得分:1)

您只需使用Math.random()获取0..1范围内的随机数,然后选择累积权重为"覆盖"的索引处的数字。随机数:

public static int random(int[] numbers, double[] weights) {
    double r = Math.random();

    double sum = 0;
    for (int i = 0; i < weights.length; i++) {
        sum += weights[i];
        if (r < sum)
            return numbers[i];
    }

    return 0; // You can only get here if sum weights is less than 1
}

此解决方案根据您在O(N)中提供的权重选择一个随机数。在大多数情况下,算法甚至不会读取整个weights数组。这是最好的。最大步长为N,平均步数为N / 2.

备注:

  • 如果较大的权重位于weights数组的开头,则该方法平均会更快。

  • 权重之和预计为1。如果权重之和小于 1,此方法可能返回0(概率为1-sum(weights))。

答案 2 :(得分:0)

1)取元素之和(S)(A [i]) 2)获取累积金额清单(C [i]) 3)从0到S-1获得随机值(R) 4)如果R&lt; C [i],你的随机值是A [i]

Cumulative Sum Range    Index in the Cumulative Array      Value in Original Array  
-----------------      -----------------------------      ----------------------
 0 <= x < 1                      0                            1
 1 <= x < 6                      1                            4
 6 <= x < 7                      2                            2