等概率随机生成不重复的数
2015-11-26 18:01
225 查看
#include <iostream> #include <cstdlib> #include <ctime>
一、1到n n个数字随机全排序,或者说,随机生成1到n n个不重复的数字
用空间换时间,需要空间复杂度为o(n),时间复杂度为o(n)
用一维数组顺序存储1到n这n个数字。
然后先在1到n中随机生成一个下标,输出该下标对应的值,然后将数组最后一个交换。并将此时最后一个从逻辑上删除。倒数第二个成为最后一个。
生成n次随机下标,问题解决。简单吧。
void generate_N_Random(int n) { int* NumPool = new int ; for(int i = 0; i < n; i++) NumPool[i] = i + 1; srand((unsigned int)time(0)); int subIndex = 0; int currentLastIndex = n - 1; for (int i = 0; i < n; i++) { subIndex = rand()%( n-i); std::cout << NumPool[subIndex] << " "; NumPool[subIndex] = NumPool[currentLastIndex]; currentLastIndex--; } endl(std::cout); delete[] NumPool; }
上面这个太简单了,稍微再加点难度。
二、用1...n 这n个数,随机生成m个不重复的数字。(m < n)
1)先用一个猥琐一点儿的方法,在前面方法的基础上取前m个数字即可。
2)新方法。时间复杂度也为o(n).
当然,还有对数复杂度的算法,那个等会儿再讲。
先来算一下概率,咱们都是学过条件概率的人。从n个数字中先m个数,每个数字被选中的概率为m/n.
举个直观点儿的例子,在0,1,2,3,4这五个数字中选两个数,我们只要保证从全局来看,每个数字被选中的概率为2/5即可,按照什么顺序选不重要。
比如,我们规定按照从0到4的顺序依次选,如果对于0,本次没有选上,那么以后也不会去选0了,所以我们要给予0这个数字2/5的选中概率。好的。
之后我们来考察1,如果刚刚0没有被选上,那么我们就要给予1这个数字2/4的选中概率。如果刚刚0被选上了,那么我们就要给予1这个数字1/4的选中概率。这样,综合来看,数字1被选中的概率就是(2/5 * 1/4 + 3/5 * 2/4) = 2/5. 符合要求。
如果已经选中了两个,即剩余要选的数字个数为0了,那么算法也就结束了。如果不为0,则同上述分析。
这样,我们就可以严格按照从0到4的顺序来等概率地选数字了。
讲解完毕。算法如下:
Knuth的《The Art of Computer Programming, Volume2:Seminumerical Algorithms》的伪代码:
select = m remaining = n for i = [0,n) if (rand() % remaining) < select print i select -- remaining--
//用算法发明者的名字来命名函数吧 void knuth(int n, int m) { srand((unsigned int)time(0)); for (int i=0; i<n; i++) { if (rand()%(n-i)<m) { std::cout << i << " "; m--; } } }
相关文章推荐
- VB与C++之间数据类型的对应关系
- HDU1541 Stars (树状数组)
- django开发要点-模型
- Eclipse - Memory Analyzer
- 门禁系统
- 图像特征LBP原理及C++实现
- Intent传递数据:从一个Activity到另一个Activity
- Oracle PL/SQL基础知识
- js中XMLHttpRequest对象实现GET、POST异步传输
- SDAccel 开发环境
- python 命令行参数,以及文件操作
- log4j详解与实战
- MongoDB数据插入、删除、更新
- Swift区间运算符
- [Javascript] instruction character 操作符, Function
- jQuery on()方法
- HBase HA中某个节点挂了导致程序运行失败
- django开发要点-URL的配置
- 节日
- SpringMVC源码解析(下)