洗牌算法(Fisher-Yates Shuffle,蓄水池抽样算法)

写在前面

博客参考:https://blog.csdn.net/qq_26399665/article/details/79831490

洗牌问题背景

从n个不同数中随机不重复不回放的取出m个数,n>=m。

洗牌算法的本质是:将原始的数组各个元素打散,是原数组各个数在打散数组中等概率出现。

洗牌算法

Fisher-Yates Shuffle算法

基本思路:从原始数组中随机取出一个之前没有取过的数放到新的数组中,具体的是随机产生一个索引rand % arr_size,然后将这个位置的数添加到结果数组中,然后将原始数组中的这个数删除掉,循环往复直至原始数组没有数。

vector<int> arr(n); //原始数组
vector<int> res; //结果数组
while (!arr.empty()) {
	int idx = rand() % arr.size();
	res.push_back(arr[idx]);
	arr.erase(arr.begin() + idx);
}

另外两个洗牌算法Knuth-Durstenfeld Shuffle,Inside-Out Algorithm就暂不介绍了。

蓄水池抽样算法

这个算法之前在博客中专门介绍过,蓄水池抽样算法步骤:

在n个数中等概率不放回取m个数,怎么取?

我们维护m大小的池子,

  1. 当接收第i个数时,i小于m,则直接放到池子中;
  2. 当i>=m时,则在[0,i]产生一个随机数d,若d落在[0,m-1]范围内,则用接收到的第i个数替换蓄水池中第d个数
  3. 反复2

蓄水池算法的本质是,若数字索引落在池子范围内,则直接放入池子,若不在池子范围内,则随机产生一个落在池子内的索引,然后将这个数字重映射到这个索引处(即替换)。

参考资料

LeetCode - 382. 链表随机节点(蓄水池采样算法)

三种洗牌算法shuffle

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值