【问题标题】:Unique random number algorithm独特的随机数算法
【发布时间】:2013-08-21 23:37:12
【问题描述】:

我想要一个算法/函数,给定一个数字 N,在恒定时间内生成从 0 到 N - 1 的随机数。在第 N 次调用之后,函数可以随心所欲。此外,算法在请求时生成数字而不是使用改组也很重要,因为我可能(并且在平均情况下)不需要完整的数字列表。最好的方法是什么?

(阅读可选)我想有一个数字哈希集,并一次提取一个数字,但这需要首先将所有元素(我通常不需要)插入哈希集中。 . 这行不通... 啊

提前感谢您的帮助。

【问题讨论】:

  • 您要的是没有显式随机播放的随机播放功能?您确实意识到在 N-1 次调用之后,返回值不再是非常随机的,对吧?而且我认为按顺序返回数字的函数(与任何其他“随机播放”一样可能)不能满足您的需求。也许您想更具体地提出您的要求?为什么不在第一次通话时随机播放?
  • 我不想在第一次调用时随机播放,因为元素列表很大,而且我平均只需要遍历前几个元素。
  • 另外,“恒定时间”是指每次调用的时间完全相同,还是只是 O(1)?此外,您完全不清楚您想要什么样的概率分布——均匀随机是最简单的,但您的规范似乎暗示您想要别的东西。
  • 那么你真正想要的是一个来自大范围(比如 M 个整数)的小随机样本(比如 N 个数字),所有样本都是唯一的,其中 N 比 M 小得多?听起来像 Bob Floyd 的算法。

标签: performance algorithm random unique


【解决方案1】:

修改Fisher–Yates shuffle,将数组替换为只存储已移动元素的映射。在 Python 中:

import random
class Shuffle:
    def __init__(self, n):
        self.d = {}
        self.n = n
    def generate(self):
        i = random.randrange(self.n)
        self.n -= 1
        di = self.d[i] if i in self.d else i  # idiomatically, self.d.get(i, i)
        dn = self.d[self.n] if self.n in self.d else self.n
        self.d[i] = dn
        self.d[self.n] = di
        return di

空间使用和摊销的预期运行时间是每个实际生成的元素 O(1) 字。根据日志因素,这是最佳的。

【讨论】:

  • 弗洛伊德的算法更简单更快。
  • 弗洛里斯上面的评论有一个链接。您将如何在此处实现它的确切细节取决于您的需求,这仍然不清楚。集合和子集有多大?你需要一个有序的集合还是只是一个组合?
  • @LeeDanielCrocker Floyd 的算法需要提前知道调用次数,并且在没有额外工作的情况下不会生成统一的随机排列。
  • 这两点都错了。您已经在上面的代码中依赖于一个现有的随机范围内的函数,并且它将使用 Floyd 使用与部分 Fisher-Yates 完全相同的参数来调用它——不可能是其他情况,否则数学将不起作用。再说一次,如果你能说明你想要什么,我可以给你代码,但是没有规范我就做不到,而且你没有给我任何规范,我可以使用。
  • @LeeDanielCrocker 它生成一个统一的随机组合,但不是一个统一的随机排列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 2011-03-09
  • 2014-12-01
  • 2010-09-24
  • 1970-01-01
相关资源
最近更新 更多