ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 取样问题 本章讲述了一个小的随机抽样问题,并用不同的方法来解决它。 问题:对于整数m和n,其中m<n,输出0~n-1范围内m个随机整数的`有序列表`, 不允许重复。 比如m=3, n=5,那么一种可能输出是0,2,3(要求有序)。实现1来自Knuth的TAOCP, 时间复杂度O(n): ~~~ void GenKnuth(int m, int n) { for(int i=0; i<n; ++i) { if((bigrand()%(n-i)) < m) { cout<<i<<endl; --m; } } } ~~~ 其中,bigrand()的作用是返回一个很大的随机整数。 实现2:在一个初始为空的集合里面插入随机整数,直到个数足够。代码如下: ~~~ 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:把包含整数0~n-1的数组顺序打乱,然后把前m个元素排序输出。 该方法的性能通常不如Knuth的算法。代码如下: ~~~ void GenShuf(int m, int n) { int x[n]; for(int i=0; i<n; ++i) x[i] = i; for(int i=0; i<m; ++i) { int j = randint(i, n-1); swap(x[i], x[j]); } sort(x, x+m); for(int i=0; i<m; ++i) cout<<x[i]<<endl; } ~~~ 深入阅读:Don Knuth的《The Art of Computer Programming, Volume 2: Seminumerical Algorithms》