随机洗牌算法
来源:互联网 发布:遭遇网络诈骗如何报案 编辑:程序博客网 时间:2024/05/16 08:01
问题:给定一个有序序列1~n,要你将其完全打乱,要求每个元素在任何一个位置出现的概率均为1/n。
解决方案:依次遍历数组,对第n个元素,以1/n的概率与前n个元素中的某个元素互换位置,最后生成的序列即满足要求,1/n的概率可通过rand() % n实现。见如下程序:
void swap(int* p, int* q)
{
int tmp = *p;
*p = *q;
*q = tmp;
}
void shuffle(int *arr, int n)
{
int i;
for(i = 0; i < n; i++) {
int idx = rand() % (i + 1); //选取互换的位置
swap(&arr[idx], &arr[i]);
}
}
使用数学归纳法证明:
l 当n=1时,idx必为0,所以元素arr[0]在任何一个位置的概率为1/1,命题成立。
l 假设当n=k时,命题成立,即n=k时,原数组中任何一个元素在任何一个位置的概率为1/k。
则当n=k+1时,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k。
当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); 在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1);
故前k个元素在任意位置的的概率都为1/(k+1)
所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。
对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-k/(k+1)) * (1/k)=1/(k+1),所以对于第k+1个元素,其在整个数组前k+1个位置上的概率也均为1/k+1。
综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。
扩展:一道google面试题
给定一个未知长度的整数流(数目大于1000),如何从中随机选取1000个随机数。
解决方法:
l 定义长度为1000的数组,对于数据流中的前1000个关键字,显然都要放到数组中。
l 对于数据流中的的第n(n>1000)个关键字,则这个关键字被随机选中的概率为 1000/n。故以 1000/n 的概率用这个关键字去替换数组中的一个。这样就可以保证所有关键字都以 1000/n的概率被选中。对于后面的关键字都进行这样的处理,这样就可以保证数组中总是保存着1000个随机关键字。
注:以1000/n的概率选择一个数替换,可通过rand() % n实现,则这个数被替换到前1000个位置中的概率为1000/n。
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- php随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- 随机洗牌算法
- [算法] 洗牌算法&随机算法
- 随机洗牌算法和随机选择算法
- 随机取样和洗牌算法
- 等概率随机洗牌算法
- 随机问题之--洗牌算法
- SQL中EXCEPT和Not in的区别?
- 每天都泡在网络里
- </br>与<p>区别
- ZJU-PAT 1077. Kuchiguse (20) 浙大2014年上机复试第一题
- 女大学生因睡觉关灯与室友起冲突 被刺8刀已毁容
- 随机洗牌算法
- Ubuntn 操作系统学习笔记之日志介绍
- JavaScript跨域总结与解决办法
- 应该有新的编程起点
- STL 智能指针
- 阿里比赛排名获取
- 大整数求和
- php 将csv文件内容导入数据库时值为空的解决
- XMPP使用TLS和auth登录