【问题标题】:Get 10000+ unique random numbers (performance) [duplicate]获得 10000 多个唯一随机数(性能)[重复]
【发布时间】:2011-12-26 02:04:34
【问题描述】:

可能重复:
Create Random Number Sequence with No Repeats

我想写一个只使用数字作为短字符串的 URL 缩短器。

我不想数,我希望下一个新数字是随机的(或伪随机)。

起初认为算法看起来像这样(伪代码):

do 
{
 number = random(0,10000)
}
while (datastore.contains(number))

datastore.store(number, url)

这个实现的问题是:由于数据存储包含的数字越多,循环执行多次的可能性就越大。性能会随着时间的推移而下降。

难道没有更好的方法来获取尚未使用的随机数吗?

【问题讨论】:

标签: performance algorithm random


【解决方案1】:

一些相关问题:# 2394246# 54059# 158716# 196017# 1608181

正确的方法取决于您将生成多少数字以及是否需要实时性能。如果您只绘制一个范围内可用数字的一小部分,则代码 sn-p 的每个数字的平均时间为 O(1),每个后续数字的时间略有增加,但仍为 O(1)。例如,请参阅问题#1608181 answer,在该问题中,我表明使用此类代码从超过2*k 的数字范围中获取k 数字是O(k)。 (该答案还具有 C 代码,可在 M<N/2 时在 O(M) 时间内从 N 个数字范围内生成 M 个数字,并解释在 M>=N/2 时如何在 O(M) 时间内使用它。)

如果你想要 O(1) 的性能和硬时间限制,你可以使用刚才提到的程序来预加载一个数组,或者可以像 Justin 所说的那样打乱整个整数范围。在该预处理之后,每次访问都是 O(1)。如果您知道您不会从 1...10000 范围内抽取超过 3000 个数字,并且没有硬性时间限制,那么您拥有的代码将平均在 O(1) 时间内运行,概率k 的通过次数减少了 0.3 ^ k; ,在最坏的情况下,1 次通过的几率约为 70%,2 次为 21%,3 次为 6%,4 次为 2%,5 次为 0.6%,依此类推。

【讨论】:

    【解决方案2】:

    使用加密。由于加密是可逆的,独特的输入产生独特的输出。对于 64 位数字,请使用 64 位块大小的密码。对于较小的块大小,例如 32 位或 16 位,请查看Hasty Pudding Cypher

    无论您需要什么大小的块,只需加密数字 0、1、2、...(以适当的块大小),即可根据需要生成尽可能多的唯一非连续数字。

    【讨论】:

    • 如果随机数必须是唯一的,并且在 0 到 10000 的范围内(如问题所示),加密并不能解决问题。
    • 如果你仔细阅读Hasty Pudding cypher的描述,你会发现它确实如此。 “Hasty Pudding 密码也可用于加密范围内的值,这些值不会转换为具有整数位的字符串;例如,它可以通过生成另一个从 0 到 N 的数字来加密从 0 到 N 的数字。它通过使用可以将输入作为位串处理的最小子密码,并将其作为位串重复应用于输入,直到输出在适当的范围内。"
    【解决方案3】:

    1) 用顺序值填充数组

    2) shuffle 数组

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      • 2023-03-16
      • 2015-03-31
      相关资源
      最近更新 更多