【蓄水池问题】太 nice 了!我中奖啦!

2024-05-01 16:20
文章标签 问题 nice 蓄水池 中奖

本文主要是介绍【蓄水池问题】太 nice 了!我中奖啦!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小伙伴们中过奖么?

是不是都是 中奖绝缘体 呢?

今天我们就来聊一聊关于中奖的 概率 问题~

先思考两个问题

如果让你从规模为 N 的数据序列中,随机选取出 k 个不重复的数据,你会怎么做呢?

  • 是不是很简单,知道了总数 N ,等概率随机选择 k 个即可,每个数据被选到的概率均为 k / N k/N k/N

问题变一下:那如果从始至终都不知道 N 的具体大小呢?也就是说,数据流长度 N 很大,数据会源源不断的到来,且 N 直到处理完所有数据之前都不可知。

如何在这样的情况下,随机选取 k 个数据,保证当前已经到来的前 i 个元素中每一个元素被选中的概率相等,均为 k / i k/i k/i ,当处理完所有数据结束时,概率自然就变为了 k / N k/N k/N 呢?

两者区别一句话总结:能否提前知道 总数据量 N 。


这就引出了今天要探讨的问题:蓄水池算法

蓄水池算法

在一个很大,未知总量的数据流中,抽取 k 个样本,并保证每个样本的选取概率都是 相等并随机 的。

算法思路

  1. 构建一个可容纳 k 个样本的数组容器。
  2. 当数据量不足 k 个时,全部选取放入数组中。
  3. 当数据量超过 k 个时(假设是第 i 个元素),以 k / i k/i k/i 的概率选择进入数组中,并以 1 / k 1/k 1/k 的概率随机替换掉数组中的一个样本元素。
  4. 无论样本数据 N 何时结束,均能保证所选元素概率均为 k / N k/N k/N

即:保证在动态情况下,已经到来的每个样本元素被选中的概率相等

证明

i ≤ k i≤k ik 时,前 m 个元素,每个被选到的概率均为 k / m k/m k/m


i > k i>k ik 时,前 m 个元素,每个被选到的概率也均为 k / m k/m k/m

由以上两种情况的证明,我们可以得出结论:

每个元素被选到的概率均等,均为 k / N k/N k/N


以上我们证明了该方法的正确性:能够在未知数据量的情况下,依然保证在新元素到来时被选中的概率相等。

代码

public static class RandomBox {// 存放被选的元素数组private int[] arr;// 抽取 k 个样本private int k;// 目前到达的样本总数private int m;// 初始化public RandomBox(int capacity) {arr = new int[capacity];        k = capacity;        m = 0;}// 等概率随机 1 ~ max 之间的一个数private int rand(int max) {return (int) (Math.random() * max) + 1;}// 新到一个元素后,进行选择public void add(int num) {// 总量+1m++;// 没超过k时,直接选入if (m <= k) {arr[m - 1] = num;} else {// 以 k/i 的概率选择进入数组if (rand(m) <= k) {// 随机替换掉其中一个元素,概率 1/karr[rand(k) - 1] = num;}}}}

实际意义

这个算法在现实中有什么意义呢?
抽奖

参与活动中大奖

今天所有参与活动的小伙伴都有几率中奖哦,今晚24:00整开奖~

假设设置了 10 个奖品,但不知道有多少个人会来参与活动,当 24:00 整时,要公布获奖名单。

此时,就可以选择“蓄水池算法”,活动结束后,遍历一遍结果数组 arr[10],所有在数组中的 10 个人就是最终的获奖者。每个人的中奖几率均为 10/今天参与活动的总人数 ,确保了活动的公平性。

你中过奖么😜
~ 点赞 ~ 关注 ~ 星标 ~ 不迷路 ~!!!

关注
回复「ACM紫书」获取 ACM 算法书籍 ~
回复「算法导论」获取 算法导论第3版 ~

点赞、转发
让你的小伙伴们一起来学算法吧!!

这篇关于【蓄水池问题】太 nice 了!我中奖啦!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/952126

相关文章

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

Mysql如何解决死锁问题

《Mysql如何解决死锁问题》:本文主要介绍Mysql如何解决死锁问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录【一】mysql中锁分类和加锁情况【1】按锁的粒度分类全局锁表级锁行级锁【2】按锁的模式分类【二】加锁方式的影响因素【三】Mysql的死锁情况【1