带上下限的红包算法

群红包总金额m,分n份,每份下限x,上限y,生成一种的随机的可行分配方案

最简单的版本,随机

思路就是先分配最小金额,然后把剩下的金额不断随机加上去,直到为0。这种不太适合流式处理。

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
public static List<Integer> generateRedPacket(int m, int n, int x, int y) {
int minTotal = n * x;
int maxTotal = n * y;
if (m > maxTotal || m < minTotal) {
return null;
}

int remaining = m - minTotal;
Random r = new Random();
List<Integer> redPacket = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
redPacket.add(x);
}

int idx = 0;
while (remaining > 0) {
int maxAddition = Math.min(y - redPacket.get(idx), remaining);
int addition = r.nextInt(maxAddition + 1);
redPacket.set(idx, addition + redPacket.get(idx));
idx++;
remaining -= addition;
}

Collections.shuffle(redPacket, r);
return redPacket;
}

二倍均值法

能保证生成10个红包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static List<Integer> generateRedPacket2(int m, int n, int x, int y) {
int minTotal = n * x;
int maxTotal = n * y;
if (m > maxTotal || m < minTotal) {
return null;
}

int remaining = m;
Random r = new Random();
List<Integer> redPacket = new ArrayList<>();
for (int i = 0; i < n; i++) {
int min = Math.max(x, remaining - (n - i - 1) * y);
int max = Math.min(y, remaining - (n - i - 1) * x);

int amount = min + r.nextInt(max - min + 1);
redPacket.add(amount);
remaining -= amount;
}

Collections.shuffle(redPacket, r);
return redPacket;
}

带上下限的红包算法
http://hhubibi.github.io/2024/08/29/redpacket/
作者
hhubibi
发布于
2024年8月29日
许可协议