【发布时间】:2018-05-11 16:20:15
【问题描述】:
Algo(来源:Elements of Programming Interviews,5.16)
给你 n 个数字和概率
p0, p1,.., pn-1总和为 1。给定一个 rand num 生成器,该生成器在[0,1]统一,你将如何生成n个数字之一 到他们的特定概率。
例子
如果数字是 3、5、7、11,概率是
9/18, 6/18, 2/18, 1/18,那么在程序的 1000000 次调用中,应该出现 3 500000次,7应该出现111111次,等等
这本书说要创建间隔p0, p0 + p1, p0 + p1 + p2, etc,所以在上面的示例中,间隔是[0.0, 5.0), [0.5, 0.0.8333), etc,并且将这些间隔组合成一个排序的端点数组可能看起来像[1/18, 3/18, 9/18, 18/18]。然后运行随机函数生成器,找到比生成元素大的最小元素——它对应的数组索引映射到给定n数字中的索引。
这需要 O(N) 预处理时间,然后需要 O(log N) 对值进行二分搜索。
我有一个需要 O(N) 预处理时间和 O(1) 执行时间的替代解决方案,我想知道它可能有什么问题。
为什么我们不能遍历n 中的每个数字,乘以[n] * 100 * probability that matches with n。例如[3] * (9/18) * 100。连接所有这些数组,最后得到一个包含 100 个元素的列表,每个映射的元素数量与它发生的可能性有关。然后,运行随机数函数并索引到数组中,并返回值。
这不是比提供的解决方案更有效吗?
【问题讨论】:
-
[1/e, 1/pi, 1/(1-e-p)]呢? -
如果抽到“4”的概率不是13%,而是13.241235123%怎么办?现在您必须生成 13241235123 个“4”,而不是在您的列表中生成 13 个“4”,而且显然还增加了其他可能的绘制值。
-
只有当个别概率是整数百分比时,您的方法才会产生准确的结果。通过选择大小为 18(或其倍数)的数组大小,您可以获得示例问题的完美结果,但通常没有理由期望概率甚至是有理数。