抢红包:二倍均值法实现均匀分配

​ 今天面蔚来被问到了,当时实现的算法不够均匀,被面试官指出了,上网搜了下,有种二倍均值法可以实现,故在此记录

1 算法介绍

​ 对于钱数money,份数person,每次计算出均值avgAmount = money / person,再将其乘2,得到下一个人可分配红包的范围,进行分配以后,moneyperson都减少,再进行该操作,最后一个人不用随机,直接取剩余金额即可

2 算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package test;

import java.io.IOException;
import java.util.Arrays;

public class Test {
public static void main(String[] args) throws IOException {
int money = 100; // 钱数
int person = 10; // 份数
int[] resultArr = clickReaPacket(money, person);
String s = Arrays.toString(resultArr);
System.out.println(s);
}

private static int[] clickReaPacket(int money, int person) {
int[] amountArr = new int[person];
System.out.printf("%s 分钱分给 %s 人\n", money, person);
for (int i = 0; i < amountArr.length - 1; i++) {
// 注意 money 和 person 两个 int 变量做除法,应该转换其中一个为浮点类型,以保存精度
double avgAmount = ((double) money) / person;
double doubleAvfAmount = avgAmount * 2;
person --;
int min = 1;
double max = doubleAvfAmount;
int currentAmount = getRandomBetween(min, max);
amountArr[i] = currentAmount;
money = money - currentAmount;
System.out.printf("剩余人数:%s\t抢到:%s \t剩余金额:%s\t本次均值的二倍:%s\t金额随机范围:[%s, %s]\n", person, currentAmount, money, doubleAvfAmount, min, max);
}
amountArr[amountArr.length - 1] = money;
return amountArr;
}

private static int getRandomBetween(int a, double b) {
double newScope = Math.random() * (b - a);
return (int) (Math.floor(a + newScope));
}
}

image-20220311155248809


抢红包:二倍均值法实现均匀分配
https://2w1nd.github.io/2022/03/11/算法/场景算法/抢红包:二倍均值法实现均匀分配/
作者
w1nd
发布于
2022年3月11日
许可协议