随机洗牌算法
来源:互联网 发布:手机网络角色游戏 编辑:程序博客网 时间:2024/05/18 09:58
算法(Java):
public HashSet getRamdomNumber(int total,int number){
//在0到total-1中随机生成number个不重复的随机数
HashSet h=new HashSet();
while(h.size()<number){
Random r=new Random();
int n=r.nextInt(total);
//n++;
}
return h;
}
第二种方法是从网上看到的,思路是:将数组的元素进行随机的交换.这个算法我不太好说,因为它的效果和效率都依赖于交换的次数N.次数越多则乱序的程度越高但是相应的效率也会降低.个人不太推荐这个算法,因为N的次数不好确定.
算法:
void shuffle ( int a[], int n ) //洗牌算法
{
int tmp = 0,p1,p2;
int cnt = rand() % 1023;
while (cnt--) //随机交换两个位置的数,共交换cnt次
{
p1 = rand() % n;
p2 = rand() % n;
tmp = a[p1];
a[p1] = a[p2];
a[p2] = tmp;
}
}
后来在看Core Java 2的时候看到了一个计算彩票的问题,实际上就是洗牌算法.思路是这样的:从数组中随机取出一个放到一个新的集合中,然后重复这个工作.这样最后原数组为空而新的集合则为乱序.这个算法比第一种算法的效率高多了,而且计算次数是固定的.当时就以为找到了最佳算法.后来蒙朋友提醒,对这个算法进行了改进.其实没有必要开辟一个新的集合的,用原来的存储空间就行.具体思路是:从数组的数中随机取出一个和最后一个元素交换,再从前面N-1个数中随机取一个和倒数第二个交换…这样可以达到和前面算法相同的效果而且存储空间也得到了节省,很不错的算法了.
算法:
void shuffle()
{
int *prev=new int[54];
for(int i=0;i<54;i++) //数组的初始化,表示54张牌
{
prev[i]=i;
}
srand(time(0));
int times=53;
while(times!=0)
{
int one=rand()%times;
swap(prev[one],prev[times]); //交换元素
times--;
}
//这个时候prev数组处于乱序状态,用完后回收空间
delete prev;
}
这是我摘自 matrix67大牛的博客的一段总结:
1. for i:=1 to n do swap(a[i], a[random(1,n)]);
2. for i:=1 to n do swap(a[i], a[random(i,n)]);
如果不仔细思考的话,绝大多数人会认为第一个算法才是真正随机的,因为它的操作“更对称”,保证了概率均等。但静下心来仔细思考,你会发现第二种算法才是真正满足随机性的。为了证明这一点,只需要注意到算法的本质是“随机确定a[1]的值,然后递归地对后n-1位进行操作”,用数学归纳法即可轻易说明算法的正确性。而事实上,这段程序一共将会产生n*(n-1)*(n-2)*…*1种等可能的情况,它们正好与1至n的n!种排列一一对应。
有人会问,那第一种算法为什么就错了呢?看它的样子多么对称美观啊……且慢,我还没说第一种算法是错的哦!虽然第一种算法将产生比第二种算法更多的可能性,会导致一些重复的数列,但完全有可能每种数列重复了相同的次数,概率仍然是均等的。事实上,更有可能发生的是,这两种算法都是正确的,不过相比之下呢第一种算法显得更加对称美观一些。为此,我们需要说明,第一种算法产生的所有情况均等地分成了n!个等价的结果。显然,这个算法将会产生n^n种情况,而我们的排列一共有n!个,因此n^n必须能够被n!整除才行(否则就不能均等地分布了)。但是,n!里含有所有不超过n的质数,而n^n里却只有n的那几个质因子。这表明要想n^n能被n!整除,n的质因子中必须含有所有不超过n的质数。这个结论看上去相当荒唐,反例遍地都是,并且直觉上告诉我们对于所有大于2的n这都是不成立的。为了证明这一点,只需要注意到2是质数,并且根据Bertrand-Chebyshev定理,在n/2和n之间一定还有一个质数。这两个质数的乘积已经大于n了。搞了半天,第一种看似对称而美观的算法居然是错的!
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- php随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- [算法] 洗牌算法&随机算法
- 随机洗牌算法和随机选择算法
- 随机取样和洗牌算法
- 等概率随机洗牌算法
- 随机问题之--洗牌算法
- Eclipse JavaEE +Tomcat 搭建web工程 servlet示例
- Sql Server查询性能优化之创建合理的索引(下篇)
- python : 随机数
- java之可变参数
- 一道小小的内存申请面试题
- 随机洗牌算法
- hdu 4284——Travel
- Struts2的配置文件——web.xml
- xcode调试命令
- 双向广搜示例:走迷宫1
- python 把自定义的函数添加到python库中的方法
- HDU 1384 && POJ 1201--Intervals 【基础差分约束】
- PAT (Advanced Level) 1044. Shopping in Mars (25) 找符合要求的连续子数组,贪心
- C++入门经典 笔记(第六章)控制程序流程