蓄水池问题

题目描述:
给出一个数据流,这个数据流的长度很大或者未知,并且对该数据流中数据只能访问一次。请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等。
或者也可以这么说:
要求从N个元素中随机的抽取k个元素,其中N的大小未知。

解题思路:
用到的方法为蓄水池抽样算法(reservoid sampling)。具体的思路是:先初始化一个集合,集合中有k个元素,将此集合作为蓄水池。然后从第k+1个元素开始遍历,并且按一定的概率替换掉蓄水池里面的元素。

伪代码:

Init : a reservoir with the size: k  
for i= k+1 to N  
    M=random(1, i);  
    if( M < k)  
     SWAP the Mth value and ith value  
end for  

具体描述如下:先将前k个数取出来放入结果集中,然后从第k+1个数开始遍历。假设遍历到第i个数,以 k/i 的概率替换掉蓄水池中的某个元素即可。

!/usr/bin/env python
#coding:utf-8

import random
import collections

#用蓄水池算法模拟从10个数中随机抽取一个数
def reservoir():
    raw_list = [0,1,2,3,4,5,6,7,8,9]
    ret_num = raw_list[0] #蓄水池初始化。因为只需要抽取一个,所以给一个变量即可

    for i in range(1,10): #从第k+1个元素开始遍历
        m = random.randint(1,i+1) #因为列表下标从0开始,所以随机数上限为i+1而不是i
        if m <= 1:
            ret_num = raw_list[i] #蓄水池里的元素替换

    return ret_num

#抽取十万次,看看最后的结果
def run():
    dic = collections.defaultdict(int)
    for i in range(100000):
        ret_num = reservoir()
        dic[ret_num] += 1

    for k,v in dic.items():
        print(k,":",v)

run()

从结果可以看出,每个数被抽到的次数基本时接近的。

0 : 9926
1 : 10024
2 : 10056
3 : 10043
4 : 10004
5 : 9826
6 : 10083
7 : 10036
8 : 9843
9 : 10159
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的蓄水池建造数学建模模板: 1.问题描述: 我们需要建造一个蓄水池来存储雨水,以供后续使用。该蓄水池需要满足以下条件: - 能够存储指定的水量 - 能够在一定时间内完成蓄水 - 能够在一定时间内排放水量 2.建模假设: - 蓄水池为圆柱形,直径为D,高度为H - 蓄水池内的水面高度为h,水位从底部开始逐渐上升 - 蓄水池的进水口和出水口均为圆形,直径分别为d1和d2 - 进水口和出水口的流量分别为Q1和Q2 - 水的密度为ρ,重力加速度为g 3.模型建立: 根据建模假设,我们可以得到以下方程组: - 体积方程:V = π/4 * D^2 * H - 进水口流量方程:Q1 = π/4 * d1^2 * v,其中v为进水口流速 - 出水口流量方程:Q2 = π/4 * d2^2 * v,其中v为出水口流速 - 蓄水池内水位方程:dh/dt = (Q1-Q2)/A,其中A为蓄水池底面积 4.求解过程: - 根据体积方程,可以计算出蓄水池的总容量V - 根据进水口和出水口的流量方程,可以计算出进水口和出水口的流速v1和v2 - 根据蓄水池内水位方程,可以计算出水位随时间的变化情况h(t) - 可以通过求解方程dh/dt = (Q1-Q2)/A,得到任意时刻的水位变化速度 5.模型验证: 为了验证模型的可靠性,可以进行以下实验: - 测量进水口和出水口的直径和流量 - 在蓄水池内加入一定量的水,并记录水位随时间的变化情况 - 根据模型计算出水位随时间的变化情况,并与实验数据进行比较 通过比较实验数据和模型计算结果,可以验证模型的可靠性,并对模型进行进一步改进和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值