解决方案(一)蓄水池抽样算法(可用于抽样,抽奖等场景)

本文介绍了蓄水池抽样算法在数据流中的应用,包括原理、Java的基本实现以及如何在模拟场景中使用,用于随机抽取指定数量的样本。作者提供了一个简单的Award类实例并指出这仅作参考,欢迎读者分享其他解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述

该算法可用于从数据流中随机抽取指定数量的样本。
假设目标样本数量为 n,参与抽样的数量为 i。
蓄水池容量为 n,参与抽样的数量为 i

每接收一个样本,不断计算抽样结果:

  • i < n 时,直接将样本留在蓄水池
  • i >= n 时,随机从 参与抽样的样本中选择一个,如果超过蓄水池水位,则淘汰新进来的元素,否则以新进来的元素替换刚刚选中的那个样本

最终每个元素的留下概率为:

  • i <= n 时,概率为 1
  • i > n 时,概率为 n i \frac {n} {i} in

Java基本实现

提供基本实现思路,实际落地适当改造

蓄水池模型

public class Award {
    /**
     * 中奖人数组
     */
    private int[] persons;
    /**
     * 参与人数
     */
    private int count;

    public Award(int award) {
        this.persons = new int[award];
    }

    /**
     * 参与抽奖
     * @param id
     */
    public void join(int id) {
        if (count < persons.length) {
            persons[count] = id;
            count++;
        } else {
            count++;
            int result = (int) (Math.random() * count);
            if (result <= persons.length - 1) {
                persons[result] = id;
            }
        }
    }

    public int[] getPersons() {
        return persons;
    }
}

参与抽样

  • 模拟抽样(实际开发中,更适合外部数据来一个计算一个抽样结果)
    抽样目标10个,样本数 10000000 个
Award award = new Award(10);
for (int i = 0; i < 10000000; i++) {
    award.join(i);
}

这个系列为个人日常分享,仅作参考。

各种解决方案欢迎留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值