从n中取出m个不重复的数

来源:互联网 发布:淘宝网页代码怎么上传 编辑:程序博客网 时间:2024/04/30 02:23

辅助函数,randint(i,j)获取[i,j]的一个随机数

int randint(int i , int j){return rand()%(j-i+1)+i;}

方法1:

从n个中取m个,当前这个数被取出的概率为n/m,即if(rand() % n < m)就被取出。

void genKnuth(unsigned int n , unsigned int m){int remain = n;int unselect = m;for (int i = 0;i<n;++i){if (rand()%remain < unselect){std::cout<<i<<std::endl;--unselect;}--remain;}}

剩下remain个数,还有unselect个未取,那么当前这个数被取出的概率为unselect/remain。要说的是从100个取20个数,这个方法必定能取出20个数。如果当前取出的以足20个,那么unselect=0,那么后面的所有数都不会被取。如果未满20个,那么后面的都有一定的概率被取到,极端情况就是前面都没有被取到,那么后面的数被取到的概率会越来越大,直到被取出的概率为1为止。

方法2:

向set中插入不重复的m个数即可。

void genSet(unsigned int n , unsigned int m){std::set<int> s;while(s.size() < m)s.insert(rand() % n);for (int i : s){std::cout<<i<<std::endl;}}

set的特点是如果有了数字t,那么再插入数字t,也只是只有一个数字t。这点和MultiSet不同。不知道的可以学习下STL。

方法3:

把牌洗乱,然后抽出20个即可。

void genShuf(int n , int m){int * x = new int[n];for (int i = 0 ; i < n ; ++i){x[i] = i;}int j;for (int i = 0 ; i < m ; ++i){j = randint(i , n-1);if (i != j){swap(x[i] , x[j]);}}sort(x,x+m);for (int i = 0 ; i < m ;++i){std::cout<<x[i]<<std::endl;}delete []x;}