假设我有一个n面加载的骰子,其中每边k 滚动时都有几率p k上升。我很好奇是否有好的算法可以静态地存储此信息(例如,用于固定的概率集),以便我可以有效地模拟骰子的随机滚动。
目前,我有一个O(lg n)解决方案。这个想法是存储一张表,列出所有k的前k个边的累积概率,它们在[0,1)范围内生成一个随机实数,并对该表执行二进制搜索以获取最大的索引,其累积值不大于所选值。我更喜欢这种解决方案,但是运行时没有考虑这些可能性似乎很奇怪。特别是,在极端情况下,一侧总是出现或值均匀分布,尽管我的解决方案仍然需要对数步,但仍可以使用天真方法在O(1)中生成滚动结果。
有人对运行时以某种“自适应”方式解决此问题有任何建议吗?
编辑 :基于对这个问题的回答,我写了 一篇文章,描述了解决这个问题的许多方法 以及它们的分析。看起来Vose对别名方法的实现为每个模具辊提供了Θ(n)预处理时间和O(1)时间,这确实令人印象深刻。希望这是对答案中包含的信息的有用补充!
您正在寻找一种别名方法,该方法提供一种 O(1) 方法,用于生成固定的离散概率分布(假定您可以在固定时间内访问长度为n的数组中的条目),并且设置为一次O(n)。 。您可以在Luc Devroye撰写的“非均匀随机变量生成”的第3章(PDF)中找到该文档。
这个想法是采用概率数组p k并产生三个新的n元素数组q k,a k和b k。每个q k是介于0和1之间的概率,每个a k和b k是介于1和n之间的整数。
我们通过在0和1之间生成两个随机数r和s来生成1和n之间的随机数。令i = floor(r * N)+1。如果q i <s,则返回a i,否则返回b i。别名方法的工作是弄清楚如何产生q k,a k和b k。