二倍均值算法-用于抢红包时,分割红包

306 阅读1分钟

1.适用场景

  1. 所有人抢得的金额总和等于红包总金额
  2. 抢得的红包至少有1分钱

2.算法设计细节

  1. 红包金额的单位设置为分
  2. 将发送的金额拆分为若干个红包保存
  3. 最后的返回值为整型数组

3.算法流程

公式:eachMoney = random(1,M/N * 2),其中M为剩余的总金额,N为未分配金额的红包个数,random()为随机数函数,其会返回[1,M/N * 2)中任意一个整数。

public class RedBagUtils {  
    /**  
    * 根据总金额和红包个数拆分为红包序列  
    *  
    * @param totalMoney  
    * @param moneyNum  
    * @return java.lang.Integer[]  
    * @author Tang  
    * @date 2023/8/26 17:03  
    **/  
    public static Integer[] generateReaBags(Integer totalMoney, Integer moneyNum) {  
        //总金额(单位为分)  
        int M = totalMoney;  
        //红包个数  
        int N = moneyNum;  
        //已分配的金额  
        int useMoney = 0;  
        Integer[] redBags = new Integer[N];  
        for (int i = 0; i < N; i++) {  
            if (i == N - 1) {  
                redBags[i] = M - useMoney;  
                break;  
            }  
            redBags[i] = new Random().nextInt((M - useMoney) / (N - i) * 2 - 1) + 1;  
            useMoney += redBags[i];  
        }  
        return redBags;  
    }  
}

4.算法优势

使得红包金额的分布尽量接近均值。

5.算法运算过程

例如:现有一个5元的红包,需要拆分为5个

  • 第一个红包:random(1,500/5 * 2),随机取值,取得73(分)
  • 第二个红包:random(1,(500-73)/(5-1) * 2),随机取值,取得130(分)
  • 第三个红包:random(1,(500-73-130)/(5-2) * 2),随机取值,取得62(分)
  • 第四个红包:random(1,(500-73-130-62)/(5-3) * 2),随机取值,取得100(分)
  • 第五个红包:最后一个红包,将剩下的金额全部分给它,为135(分)

(上述数据为某次测试的结果)