1.问题描述
程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。从概率的角度说,我们希望得到没有重复的有序选择,其中每个选择出现的概率相等。
2.解决思路与代码实现
编程珠玑上给出了四个函数
1).genknuth():算法依次考虑整数0,1,2,...,n-1,并通过一个适当的随机测试对每个整数进行选择。通过按序访问整数,可以保证输出结果是有序的
代码C++实现:
void genknuth(int m, int n) { for(int i = 0;i < 0;i++) { if((bigrand() % (n-i)) < m) { cout << i << "\n"; m--; } } }
2).gensets():一种解决方案是在一个初始为空的集合里面插入随机整数,直到个数足够,这里利用C++ set容器
void gensets(int m, int n) { set<int> S; while(S.size() < m) S.insert(bigrand() % n); set<int>::iterator i; for(i = S.begin(); i != S.end(); ++i) cout << *i << endl; }
3).genshuffle():生成随机整数的有序子集的另一种方法是把包含整数0~n-1的数组的前m个元素打乱,然后把前m个元素排序输出。
void genshuf(int m, int n) { int i,j; int *x = new int[n]; for(i = 0; i < n; i++) x[i] = i; for(i = 0; i < m; i++) { j = randint(i, n-1); int t = x[i]; x[i] = x[j]; x[j] = t; } sort(x , x+m); for(i = 0; i < m; i++) cout << x[i] << endl; }
4).genfloyd():m和n接近的时候,基于2)的改进,并能在m个步骤之内就可以按要求等概率地生成有序随机数
void genfloyd(int m, int n) { set<int> S; set<int>::iterator i; for(int j = n-m; j < n; j++) { int t = bigrand() % (j+1); if(S.find(t) == S.end()) S.insert(t); //t not in S else S.insert(j); //t in S } for(i = S.begin(); i != S.end(); ++i) cout << *i << endl; }