【算法专题 - 应用场景】
【题目】
微信红包大家肯定都不陌生,但你是否思考过一个问题:当你通过微信针对某个群发出一个红包时,微信系统如何分配特定额度的money给群里用户的?随机分配?先抢到红包的用户是否一定可以获取到更多的money?
【问题分析】
无论红包金额如何分配,可以确定的是分配规则需要遵从下述三点:
1. 所有红包总和是固定的;
2. 最小的红包金额不能小于0.01元 – 可以使用微信发送红包确认;
3. 红包个数不大于当前群成员个数;
【解决方案】
假设红包总金额为100元,红包数量为10个:
- 相对随机分配
最简单的随机分配规则:不同红包的金额在区间[0.01, 剩余金额]中。第一个红包区间[0.01, 100],假设最终取值为15,则第二个红包区间为[0.01, 100-15], …
此方法存在一个弊端:随着剩余金额的减少,红包金额随之减少,也就是先下手拆红包者有更大的概率获取到金额较大的红包。
- 相对均衡分配 – 二倍均值法
为了避免上述方法存在的弊端,我们可以考虑使得每个红包的金额接近于平均值100/10,也就是10元,那么对应的每个红包金额被限定在区间[0.01, 20]中,也即[0.01, (100/10)*2]。
此方法可以保证大多数红包金额随机分布在一某一个固定值(10)附近,但是允许部分个别红包的金额偏离这一均值,比如最后一个红包完全由前面9个红包的金额来确定,其值可能会远远偏离上述均值。故此方法并非完全意义上的平均分配。
- 完全随机分配
上述两种分配规则整体的思路是逐步分配红包:来一个抢红包请求,分配一个红包出来,后一个红包的金额范围受限于前面红包的实际金额。仔细思考,抢红包类似一个并发请。针对并发请求,负责红包分配的系统完全可以事先分配好红包,然后将红包随机分配给到达的抢红包请求。
将问题进行转化:将额度为100元的红包看作一段长度为100cm的线段,现在需要将其随机切割成10条线段。为了达到这一需求,我们在区间[1, 100) 内找出随机分布的9个点即可。