小编典典

O(1)中的唯一(非重复)随机数?

algorithm

我想生成一个介于0到1000之间的永不重复的唯一随机数(即6不会出现两次),但是这并不能像对先前值进行O(N)搜索那样进行。这可能吗?


阅读 270

收藏
2020-07-28

共1个答案

小编典典

使用0-1000值初始化一个1001个整数的数组,并将变量max设置为数组的当前max索引(从1000开始)。选择一个介于0和max之间的随机数r,将位置r处的数字与位置max处的数字交换,然后立即将位置max处的数字返回。最大减1,然后继续。当max为0时,将max设置回数组的大小-1,然后重新启动,而无需重新初始化数组。

更新:
尽管我回答问题时是自己提出了这种方法,但是经过一些研究后,我意识到这是费舍尔·耶茨的改良版,称为Durstenfeld-
Fisher-Yates或Knuth-Fisher-Yates。由于描述可能会有些困难,因此我在下面提供了一个示例(使用11个元素而不是1001):

数组以初始化为array [n] = n的11个元素开始,最大值从10开始:

+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|
+--+--+--+--+--+--+--+--+--+--+--+
                                ^
                               max

每次迭代时,都会在0到max之间选择一个随机数r,将array [r]和array [max]交换,返回新的array [max],并将max减1:

max = 10, r = 3
           +--------------------+
           v                    v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2|10| 4| 5| 6| 7| 8| 9| 3|
+--+--+--+--+--+--+--+--+--+--+--+

max = 9, r = 7
                       +-----+
                       v     v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2|10| 4| 5| 6| 9| 8| 7: 3|
+--+--+--+--+--+--+--+--+--+--+--+

max = 8, r = 1
     +--------------------+
     v                    v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 8| 2|10| 4| 5| 6| 9| 1: 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+

max = 7, r = 5
                 +-----+
                 v     v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 8| 2|10| 4| 9| 6| 5: 1| 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+

...

经过11次迭代后,已选择数组中的所有数字,max == 0,并且对数组元素进行了混洗:

+--+--+--+--+--+--+--+--+--+--+--+
| 4|10| 8| 6| 2| 0| 9| 5| 1| 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+

此时,最大可以重置为10,并且该过程可以继续。

2020-07-28