专栏名称: 数盟
数盟(数据科学家联盟)隶属于北京数盟科技有限公司,数盟致力于成为培养与发现“数据科学家”的黄埔军校。 数盟服务包括:线下活动、大数据培训。 官网:http://dataunion.org,合作:[email protected]
目录
相关文章推荐
大数据分析和人工智能  ·  免费领取DeepSeek教程 ·  昨天  
软件定义世界(SDX)  ·  与孙正义对话,Sam ... ·  2 天前  
天池大数据科研平台  ·  谷歌反击,最强Gemini ... ·  昨天  
CDA数据分析师  ·  【干货】画用户画像与找相亲对象一样简单 ·  昨天  
大数据分析和人工智能  ·  35岁被优化,经济压力大,看DeepSeek ... ·  4 天前  
51好读  ›  专栏  ›  数盟

漫画:如何实现抢红包算法?

数盟  · 公众号  · 大数据  · 2018-05-03 22:00

正文

点击上方“ 程序员小灰 ”,选择“置顶公众号”

有趣有内涵的文章第一时间送达!













发出一个固定金额的红包,由若干个人来抢,需要满足哪些规则?


1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。


2.每个人至少抢到一分钱。


3.要保证所有人抢到金额的几率相等。





小灰的思路是什么样呢?


每次抢到的金额 = 随机区间 ( 0,  剩余金额 )





为什么这么说呢?让我们看一个栗子:


假设有10个人,红包总额100元。


第一个人的随机范围是 (0,100元) ,平均可以抢到 50元


假设第一个人随机到50元,那么剩余金额是100-50 = 50 元。


第二个人的随机范围是 (0, 50元) ,平均可以抢到 25元


假设第二个人随机到25元,那么剩余金额是50-25 = 25 元。


第三个人的随机范围是 (0, 25元) ,平均可以抢到 12.5元


以此类推,每一次随机范围越来越小。







方法1:二倍均值法


剩余红包金额为M,剩余人数为N,那么有如下公式:


每次抢到的金额 = 随机区间 (0, M / N X 2)


这个公式,保证了 每次随机金额的平均值是相等的 ,不会因为抢红包的先后顺序而造成不公平。


举个栗子:


假设有10个人,红包总额100元。


100/10X2 = 20, 所以第一个人的随机范围是 (0,20 ) ,平均可以抢到 10元


假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。


90/9X2 = 20, 所以第二个人的随机范围同样是 (0,20 ) ,平均可以抢到 10元


假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。


80/8X2 = 20, 所以第三个人的随机范围同样是 (0,20 ) ,平均可以抢到 10元


以此类推,每一次随机范围的均值是相等的。





  1. //发红包算法,金额参数以分为单位

  2. public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum){

  3.    List<Integer> amountList = new ArrayList<Integer>();

  4.    Integer restAmount = totalAmount;

  5.    Integer restPeopleNum = totalPeopleNum;

  6.    Random random = new Random();

  7.    for(int i=0; i1; i++){

  8.        //随机范围:[1,剩余人均金额的两倍),左闭右开

  9.        int amount = random.nextInt(restAmount / restPeopleNum * 2 - 1) + 1;

  10.        restAmount -= amount;

  11.        restPeopleNum --;

  12.        amountList.add(amount);

  13.    }

  14.    amountList.add(restAmount);

  15.    return amountList;

  16. }

  17. public static void main(String[] args){

  18.    List<Integer> amountList = divideRedPackage(5000, 30);

  19.    for(Integer amount : amountList){

  20.        System.out.println("抢到金额:" + new BigDecimal(amount).divide(new BigDecimal(100)));

  21.    }







请到「今天看啥」查看全文