面试题80:海量数据等概论抽样(蓄水池问题)

2024-04-06 17:38

本文主要是介绍面试题80:海量数据等概论抽样(蓄水池问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:

从N个元素中随机抽取K个元素,N的个数不确定,要求保证每个数字被抽中的概率相等。

解读:

这种应用的场景一般是数据流的情况下,由于数据只能被读取一次,而且数据量很大,并不能全部保存,因此数据量N是无法在抽样开始时确定的;但又要保证概率相等。

解决:

解决方案就是蓄水池抽样。主要思想就是保持一个集合(这个集合最终的数字就是被抽中的数字)。依次遍历所有数据的时候以一定的概率替换掉这个蓄水池中的数字。

其伪代码为:

Init : a reservoir with the size: k   //初始化蓄水池为前K个数for    i= k+1 to N  M=random(1, i);if( M < k)SWAP the Mth value and ith valueend for
程序的开始就是把前K个元素都放到水库中,然后对之后的第i个元素,以k/i的概率替换掉这个水库中的某一个元素。

证明概率相等:

首先要明白,如果最终K个元素确定,则这K个元素出现的概率都是K/N。

下面来证明当读到第i个元素时,水库中每个元素出现的概率是K/i。

1)初始情况:出现在水库中的K个元素出现的概率都是1.

2)第一步:处理第K+1个元素的情况。分为两种情况:水库中元素都没有被替换;水库中某个元素被第K+1个元素替换掉。

对于情况2:第K+1个元素被选中的概率是K/(K+1),所以这个新元素在水库中出现的概率就一定是K/(K+1)。下面看水库中剩余的元素出现的概率。水库中人一个元素被替换的概率是1/(K+1),那它出现在水库中的概率就是K/(K+1)。可以看出新元素和旧元素出现的概率是相等的。
对于情况1:当元素全部都没有替换掉的时候,每个元素的出现概率肯定是一样的,这很显然。但具体是多少呢?就是1-P(第k+1个元素被选中)=1-1/(k+1)=K/(k+1)。

即i=K+1的时候满足

3)归纳法:重复上面的过程,只要证明第i步到第i+1步,所有元素出现的概率相等即可。

假设第i个元素也满足水库中每个元素出现的概率是K/i,则当第i+1个元素时:
第i+1个元素出现在水池中的概率为K/(i+1),很容易得到水库中其他元素出现的概率也是K/(i+1)。


下面利用上面的方法从1-100之间选出3个数:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;const int N = 100;
const int poolN = 3;int Random(int min, int max)
{return min + rand() % (max - min + 1);
}void Draw()
{int source[N];int re[poolN];for (int i = 0; i < N; i++) source[i] = i + 1;for (int i = 0; i < poolN; i++) re[i] = source[i];for (int k = poolN; k < N; k++){int temp = Random(0, k-1);if (temp < poolN) swap(re[temp], source[k]);}for (int i = 0; i < poolN; i++)cout << re[i] << " ";cout << endl;
}int main()
{srand((unsigned int)time(NULL));for (int i = 0; i < 100;i++)Draw();return 0;
}
感觉有点问题,能够保证Random(min,max)产生的[min,max]中每个数的概率相等吗?

这篇关于面试题80:海量数据等概论抽样(蓄水池问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结