红包算法有很多,比如二倍均值法,线段切割法等。一般来说,需要满足的规则有以下几点:
1. 所有人抢到的金额之和要等于红包金额,不能多也不能少。
2. 每个人至少抢到1分钱。
3. 要保证红包拆分的金额尽可能分布均衡,不要出现两极分化太严重的情况。
public class RedPackage {
public static void main(String[] args) {
RedPackage redPackage = new RedPackage();
redPackage.print(redPackage.divideRedPackageV1(5, 1));
redPackage.print(redPackage.divideRedPackageV1(5, 5));
redPackage.print(redPackage.divideRedPackageV1(100, 5));
redPackage.print(redPackage.divideRedPackageV2(5, 1));
redPackage.print(redPackage.divideRedPackageV2(5, 5));
redPackage.print(redPackage.divideRedPackageV2(100, 5));
}
private void print(List<Integer> list) {
for (Integer amount : list) {
System.out.print(amount + " ");
}
System.out.println();
}
/**
* 拆分红包-二倍均值法,每个红包的大小为:[1,(剩余红包金额/剩余人数 )* 2-1]
* 注意边界:如5分钱红包发5个人
*
* @param totalAmount 总金额 分
* @param personNum 总人数
* @return 红包金额集合
*/
private List<Integer> divideRedPackageV1(Integer totalAmount, Integer personNum) {
List<Integer> amountList = new LinkedList<>();
Random random = new Random();
Integer leftAmount = totalAmount;
Integer leftPerson = personNum;
for (int i = 0; i < personNum - 1; i++) {
//二倍均值法
Integer amount = random.nextInt(leftAmount / leftPerson * 2 - 1) + 1;
amountList.add(amount);
leftAmount -= amount;
leftPerson--;
}
amountList.add(leftAmount);
return amountList;
}
/**
* 拆分红包-线段切割法,[1,总金额-1]
* 将红包比作一条线段,对线段进行personNum-1次,即分成personNum段。
* 每一段的长度即为红包的大小
*
* @param totalAmount 总金额 分
* @param personNum 总人数
* @return 红包金额集合
*/
private List<Integer> divideRedPackageV2(Integer totalAmount, Integer personNum) {
List<Integer> separateList = new LinkedList<>();
List<Integer> amountList = new LinkedList<>();
if (personNum == 1) {
amountList.add(totalAmount);
return amountList;
}
Random random = new Random();
while (separateList.size() < personNum - 1) {
//对红包线段切割personNum - 1次
Integer separate = random.nextInt(totalAmount - 1) + 1;
if (separateList.contains(separate)) {
continue;
}
separateList.add(separate);
}
separateList.add(0);
separateList.add(totalAmount);
//集合排序
Collections.sort(separateList);
//计算线段长度即红包大小
for (int i = 0; i < separateList.size() - 1; i++) {
amountList.add(separateList.get(i + 1) - separateList.get(i));
}
return amountList;
}
}