生成 2 个范围内的随机非重复数字对

Generate random non repeating pairs of numbers within 2 ranges

我想创建 2 个范围内的随机数字对。

例如,如果我想要 3 个随机数字对,其中 10 < n1 < 20 和 30 < n2 < 50 那么可接受的输出将是这样的:[[11,35],[15,30],[15,42]] 但不是 [[11,35],[11,35],[12,39]]

我想要一个高效(计算和内存方面)的算法来执行此操作。语言并不重要,因为我可以稍后调整它(尽管 Python 是首选)。

到目前为止,我最好的想法是创建一个字典,其中包含 n1 中所有可能的数字,并将 n2 中使用的数字列表作为值。然后我可以随机选择一个 n1 并找到一个没有在 n1[n2] 集合中使用过的数字。

虽然这不是很有效 space 明智,但我希望有更好的东西。多次查找不在 n1[n2] 中的数字似乎在计算上也很低效。

我也可以反其道而行之,用所有未使用的数字填充字典,然后从列表中弹出一个随机数。但这会使用更多 space.

有什么有效的方法吗?这是一个常见问题吗?

编辑:如果这可以很容易地扩展到更多维度(所以 N 个数字的集合),那就太好了。但这还不是真正需要的。

[min_x, min_x + s) X [min_y, min_y + t)中的整数对(x, y)可以通过计算m = x * t + y - min_y映射到一维space[min_x * t, (min_x + s) * t)中的整数m .从m(x, y)的逆映射可以通过Python中的(m // t, min_y + m % t)实现。

因此问题转化为从 [min_x * t, (min_x + s) * t) 中选择多个值而不进行替换(即返回序列中没有重复项)。这可以通过简单地调用 Python 中的 random.sample 函数来完成。根据文档,底层实现对于序列输入是 space 高效的。所以整个问题可以在Python中完成如下所示:

from random import sample

# max_x and max_y are exclusive while min_x and min_y are inclusive
t = max_y - min_y
sampled_pairs = [(m//t, min_y + m%t) for m in sample(range(min_x * t, max_x * t), k=3)]