【发布时间】:2020-10-14 17:21:14
【问题描述】:
假设我有一个randint(A, B) 函数,它在[A, B] (包括)范围内生成一个均匀分布的随机整数。例如,1 <= randint(1, 10) <= 10。如何在一定范围内高效地随机生成 3 个不同的整数?
这应该通过对 randint(A, B) 的 3 次调用来完成。我不在乎我得到的三个数字的哪个排列;它可以是随机的或具有定义的顺序。
我不只是试图找到任何算法来做到这一点,而是(在合理范围内)使用最少额外内存的最快算法。
def rand3(low, high):
assert high - low + 1 >= 3
# Magic!
return n1, n2, n3 # each number has low <= n <= high, each number is distinct
最简单的方法是生成一个数字列表[low, low + 1, ..., high],然后执行 Fisher-Yates 洗牌以选择 3 个元素,尽管成本很高。没有必要全面评估 Fischer-Yates,因为我们可以滚动三个指数。但是,我绝对不想在内存中创建这个数组。
对于 2 个整数,将范围内的第二个整数滚动小于一个就足够了,如果它大于或等于第一个数字,则向上调整其值:
def rand2(low, high):
i1 = randint(low, high)
i2 = randint(low, high - 1)
n1 = i1
n2 = i2 + (i2 >= n1)
return n1, n2
但是,将其扩展到三个整数并不简单。我相信应该可以做这样的事情:
# I _think_ this works?
def rand3(low, high):
i1 = randint(low, high)
i2 = randint(low, high - 1)
i3 = randint(low, high - 2)
n1 = i1
n2 = i2 + (i2 >= n1)
if n1 > n2: n1, n2 = n2, n1
n3 = i3 + (i3 >= n1)
n3 = n3 + (n3 >= n2)
return n1, n2, n3
但是,我觉得必须有比这更简单的东西。 3 元素问题真的要复杂得多,以至于我们需要对 2 个整数进行排序并且第二个条件 (n3 >= n2) 必须依赖于 n3 的中间值吗?我期待更接近 2 元素问题的东西。
【问题讨论】:
-
也称为“从一个区间中抽取 3 个随机整数而不进行替换”