从[0, N-1] 范围开始,然后使用0s 和1s 执行二分查找:
例如当 N = 16 时,您从 [0, 15] 开始,序列 0, 1, 1, 0 将给出:
[0, 7]
[4, 7]
[6, 7]
[6]
如果 N 不是 2 的幂,那么在任何迭代中,剩余数字列表的长度可能是奇数,在这种情况下,需要决定将中间数字作为下半部分的一部分或上半部分。这可以在算法开始时决定。滚动一次:0 表示包含所有中间数字的实例到下半部分,1 表示包含所有中间数字的实例到右半部分。
与生成log(N) 位并获取或获取mod N 的常用方法相比,我认为这至少更接近您要求的均匀分布。
为了说明我的意思,使用我的方法在[0, 9]范围内生成一个数字:
To generate 0
0: 0, 0, 0, 0
1: 0, 0, 0
To generate 1
0: 0, 0, 0, 1
1: 0, 0, 1
To generate 2
0: 0, 0, 1
1: 0, 1, 0
To generate 3
0: 0, 1, 0
1: 0, 1, 1, 0
To generate 4
0: 0, 1, 1
1: 0, 1, 1, 1
To generate 5
0: 1, 0, 0, 0
1: 1, 0, 0
To generate 6
0: 1, 0, 0, 1
1: 1, 0, 1
To generate 7
0: 1, 0, 1
1: 1, 1, 0
To generate 8
0: 1, 1, 0
1: 1, 1, 1, 0
To generate 9
0: 1, 1, 1
1: 1, 1, 1, 1
另一个简单的答案是生成一个足够大的二进制数,这样采用mod N 就不会(从统计上)偏爱某些数字而不是其他数字。但我认为您也不会喜欢这个答案,因为从您的 cmets 到另一个答案来看,您似乎在考虑生成位数方面的效率。
简而言之,我不确定为什么我对这个答案投了反对票,因为与它使用的位数相比,这个算法似乎提供了一个很好的分布 (~log(N))。