您需要从 [0, N) 范围内生成 M 个均匀分布的随机数,但这里有一个警告。
需要注意的是,您对问题的陈述是模棱两可的。均匀分布的选择是什么意思?一件事是说必须以相等的概率(当然是 M/N)选择每个索引。另一件事是说必须以相等的概率选择每个双指数组合。这两个是不一样的。你想到了哪一个?
如果 M 远小于 N,则在 [0, N) 范围内选择 M 个数字的经典算法是 Bob Floyd 算法,该算法可在 Bentley 的“Programming Peals”一书中找到。它看起来如下(草图)
for (int j = N - M; i < N; ++j) {
int rand = random(0, j); // generate a random integer in range [0, j]
if (`rand` has not been generated before)
output rand;
else
output j;
}
为了检查是否已经为相对较高的 M 生成了 rand,需要对集合进行某种实现,但在您的情况下,M=2 很简单。
请注意,此算法均匀分布 M 个数字的集合。此外,该算法需要精确的 M 次迭代(尝试)来生成 M 个随机数,即它不遵循在旨在解决同一问题的各种 ad-hoc 算法中经常使用的有缺陷的“试错”方法。
根据您的具体情况调整上述内容,正确的算法如下所示
first = random(0, N - 2);
second = random(0, N - 1);
if (second == first)
second = N - 1;
(我省略了random(a, b) 的内部细节作为实现细节)。
为什么上面的工作正确并产生真正均匀的分布可能不是很明显,但确实如此:)