【发布时间】:2017-06-28 15:05:19
【问题描述】:
假设您需要生成前 N 个整数的随机排列。例如,{4, 3, 1, 5, 2} 和 {3, 1, 4, 2, 5} 是合法排列,但 {5, 4, 1, 2, 1} 不是,因为一个数 (1 ) 重复,而另一个 (3) 丢失。该例程通常用于算法的模拟。我们假设存在一个随机数生成器 RandInt(i,j),它以相等的概率在 i 和 j 之间生成。这是算法:
将数组 A 从 A[0] 填充到 A[N-1],如下所示:要填充 A[i],生成随机数,直到得到一个不在 A[0]、A[1] 中的随机数,…, A[i-1].
用 C++ 实现这个算法并找出复杂度。这是我的代码:
int a;
bool b = false;
A[0] = RandInt(1,n);
for (int i=1;i<n;i++) {
do {
b = false;
a = RandInt(1,n);
for (int j=0;j<i;j++)
if(A[j] == a)
b = true;
} while(b);
A[i] = a;
}
这段代码正确吗?我怎样才能找到算法的复杂性?由于 RandInt(i,j) 生成随机数,我不知道 do while 循环将重复多少次。
【问题讨论】:
-
如果序列少于大约 1,000,000,000 个值:用序列中的值填充数组,并使用成对的随机数通过交换值来打乱数组。至少进行与数组大小一样多的交换。要审核工作代码,请在 Code Review 上发帖:codereview.stackexchange.com
-
@RichardCritten 更好的方法是 Fisher–Yates shuffle 或
std::shuffle,这可以保证均匀分布,但 OP 坚持使用他被告知无论如何都要使用的技术。 -
shuffle由iota提供的向量。 -
生成随机数,然后添加到
std::set,这将自动消除重复。当set的大小达到所需值时停止添加。对于复杂性,您需要查看随着set的大小增加而选择已选择号码的概率。
标签: c++ arrays algorithm random