我想写一个只使用数字作为短字符串的URL缩短器。
我不想数数,我希望下一个新数字是随机的(或伪随机)。
首先,思想算法看起来像这样(伪代码):
do
{
number = random(0,10000)
}
while (datastore.contains(number))
datastore.store(number, url)
此实现的问题是:由于数据存储包含更多数字,因此循环将多次执行的可能性越大。性能会随着时间的推移而降低。
是否有更好的方法来获取尚未使用的随机数?
答案 0 :(得分:5)
1)用连续值填充数组
2)shuffle数组
答案 1 :(得分:1)
使用加密。由于加密是可逆的,因此唯一输入会产生唯一输出。对于64位数字,请使用具有64位块大小的密码。对于较小的块大小,例如32位或16位,请查看Hasty Pudding Cypher。
无论您需要哪种块大小,只需加密数字0,1,2 ......(以适当的块大小)即可生成所需数量的唯一非序列号。
答案 2 :(得分:0)
一些相关问题:# 2394246,# 54059,# 158716,# 196017和# 1608181。
正确的方法取决于您将生成多少数字,以及是否需要实时性能。如果您绘制的范围不超过某个范围内可用数字的一小部分,则代码段的平均每个数字时间为O(1),每个后期数字的时间略有增加,但仍为O(1)。例如,请参阅问题#1608181 answer,其中我展示了使用此类代码从k
个数字中获取2*k
个数字O(k)
为M<N/2
。 (该答案还具有C代码,用于在M>=N/2
的O(M)时间内从N个数字的范围生成M个数字,并解释在k
时如何将其用于O(M)时间。 )
如果你想要O(1)性能有一个硬时间限制,你可以使用刚刚提到的程序来预加载一个数组,或者可以改组整个范围的整数,如Justin所述。在预处理之后,每次访问都是O(1)。如果你知道你不会从你的1 ... 10000范围内抽取超过3000个数字,并且没有硬限时,那么你所拥有的代码将平均在O(1)时间内运行{{1}}的通过量减少了0.3 ^ k; 即,最差约为70%的可能性为1次通过,21%为2次,6%为3次,2%为4次,0.6%为5次,等等。