二倍均值法
假设人数为 N,钱数为 M,且都为整数。每次分配的红包为 [0, 2*M/N] 之间的某个随机数,那么分配的红包数额的均值为 M/N。
该算法可以保证每次分配的红包均值都为 M/N,但是并不能保证每个红包的均值都一样,因为 M 和 N 一直在变化,那么 M/N 的值就会不同。
| N | M | 红包 |
|---|---|---|
| 5 | 10 | 2 |
| 4 | 8 | 2 |
| 3 | 6 | 2 |
| 2 | 4 | 2 |
| 1 | 2 | 2 |
List<Integer> generatePacketsByDoubleMean(int people, int money) {
List<Integer> packets = new ArrayList<>();
Random random = new Random();
while (people > 1) {
int p = random.nextInt(2 * money / people);
packets.add(p);
money -= p;
people--;
}
packets.add(money);
return packets;
}
线段切割法
在一条线段上找 N-1 个随机点,就可以将该线段随机且公平地切割成 N 段。
List<Integer> generatePacketsByLineCutting(int people, int money) {
List<Integer> packets = new ArrayList<>();
Random random = new Random();
Set<Integer> points = new TreeSet<>();
while (points.size() < people - 1) {
points.add(random.nextInt(money - 1));
}
points.add(money);
int pre = 0;
for (int p : points) {
packets.add(p - pre);
pre = p;
}
return packets;
}